Closed craigfowler closed 5 years ago
Here are my initial thoughts for this. It will need to take a dependency upon CSF.Specifications because of the need to create spec types which are used to test for available types.
These notes also contain some of the ideas for https://github.com/csf-dev/CSF.Reflection/issues/4
public interface IGetsTypes
{
IEnumerable<Type> GetTypes();
}
public abstract class AssemblyTypeProvider : IGetsTypes
{
public virtual IEnumerable<Type> GetTypes()
{
return GetType()
.Assembly
.GetExportedTypes();
}
}
public class IsConcreteSpecification : SpecificationExpression<Type>
{
public override GetExpression() => x => x.IsClass && !x.IsAbstract;
}
public class DerivesFromSpecification : SpecificationExpression<Type>
{
readonly Type baseType;
public override GetExpression()
=> x => baseType.IsAssignableFrom(x);
public DerivesFromSpecification(Type baseType)
{
// TODO: Null check
this.baseType = baseType;
}
}
public class MyFunkyTypeProvider : IGetsTypes
{
public IEnumerable<Type> GetTypes()
{
var assemblyOneTypes = new AssemblyOneTypeProvider().GetTypes();
var assemblyTwoTypes = new AssemblyTwoTypeProvider().GetTypes();
return assemblyOneTypes
.Union(assemblyTwoTypes)
.Where(new IsConcreteSpecification())
.Where(new DerivesFromSpecification(typeof(IIsFunky)))
.ToArray();
}
}
This will become what I use to replace calls to the static
typeof(SomeClass).Assembly.GetExportedTypes();
.I'd like to create an interface for a service which exposes a single method which returns an
IEnumerable<Type>
. A given solution may have many implementations, where each implementation should get a single classification of types which do not need further filtering or querying.Rationale
I'd like to do this mainly for dependency injection registrations. In particular where I'm writing a registration which is essentially:
This could be used any other time I want to reflect a collection of types from one or more assemblies, which match a given specification though.
Example of planned usage