C# how to create class instance by class attributes - c#

How do I create a class instance using known attributes?
In this the attributes are values of an enum.
public enum MyEnum
{
Value1,
Value2
}
class MyAttribute : Attribute... //attribute definition class
{ //uses the enum}
//Main
abstract class MyMain ...
{
public static MyMain CreateClass
{
MyMain newInheritedClass = ?
}
}
[MyAttribute(MyEnum.Value1)]
class MyClassA : MyMain ...
[MyAttribute(MyEnum.Value2)]
class MyClassB : MyMain ...

I competely agree with Fabio's answer in that using attributes seems an overkill here but we don't have enough information to really know why you are using this approach so I'll show you how it would be done:
Your method CreateClass should look like this:
public static MyMain CreateClass(MyEnum value)
{
var targetType = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsSubclassOf(typeof(MyMain)) &&
t.GetCustomAttribute<MyAttribute>()?.Value == value)
.FirstOrDefault();
if (targetType != null)
return Activator.CreateInstance(targetType) as MyMain;
return null;
}
This presuposes two things:
Your derived classes are defined in the executing assembly.
Your derived classes have public parameterless constructors.
If niether is the case you can still adapt the solution investigating a little.

For the purposes you describe in comments I think using attributes is little bid overkill.
Just create a static method or factory class with method which will do the same things:
public static MyMain CreateInstance(MyEnum attribute)
{
if(attribute == MyEnum.Value1)
{
return new MyClassA();
}
else
{
//...
}
}
Of course if you have a task to create instance based on the attributes then:
private readonly Dictionary<MyEnum, Type> _Data;
public Factory(Assembly assembly)
{
var myAttributeClasses =
assembly.GetTypes()
.Select(t => new
{
DirevedType = t,
Attribute = (MyAttribute)t.GetCustomAttribute(typeof(MyAttribute))
})
.Where(data => data.Attribute != null);
_Data = new Dictionary<MyEnum, Type>();
foreach(var data in myAttributeClasses)
{
_Data.Add(data.Attribute.EnumValue, data.DerivedType);
}
}
public MyMain CreateInstance(MyEnum enumvalue)
{
Type derivedType;
if(_Data.TryGetValue(enumvalue, out derivedType) == false)
return null;
return Activator.CreateInstance(derivedType);
}

Related

Check if class is a subclass of specific generic

I have the following classes:
public class HtSecurePage : UserControl, IDisposable
{
}
public class HtSecureInstancePage<T1> : HtSecurePage
{
}
public partial class NormalPage : HtSecurePage
{
}
public partial class InstancePage : HtSecureInstancePage<ZlsManager>
{
}
To check if NormalPage is a subClass of HtSecurePage I use the following pattern.
if (typeof(NormalPage).BaseType == typeof(HtSecurePage))
{
}
If I use this pattern against InstancePage, it is not working.
if (typeof(InstancePage).BaseType == typeof(HtSecureInstancePage<>))
{
}
I need to know if a Type is a direct subClass of HtSecurePage or HtSecureInstancePage<>. (It's important not to check against HtSecureInstancePage<ZlsManager>!) The Type T1 is unknown.
Below function check your class' sub-class the same type supplied class. If types is generic, check operation is executed over generic type definition.
Method usage
bool isInherited = CheckIsDirectlyInherited(typeof(TestAbstract), new[] {typeof(SecondLevelAbstractClass), typeof(FirstLevelAbstract)});
Method
bool CheckIsDirectlyInherited(Type obj, Type[] baseTypes)
{
if (obj.BaseType == null)
return false;
var objGenericDefinition = obj.BaseType;
if (objGenericDefinition.IsGenericType)
{
objGenericDefinition = objGenericDefinition.GetGenericTypeDefinition();
}
foreach (Type baseType in baseTypes)
{
var baseTypeDefinition = baseType;
if (baseTypeDefinition.IsGenericType)
baseTypeDefinition = baseType.GetGenericTypeDefinition();
if (objGenericDefinition == baseTypeDefinition)
return true;
}
return false;
}
is a direct subClass of HtSecurePage
I think you already know how to do it
Console.WriteLine(typeof(HtSecureInstancePage<ZlsManager>).BaseType == typeof(HtSecurePage));
is a direct subClass of HtSecureInstancePage<>
To check it you can use something like this:
static bool IsDirectSubclassOfRawGeneric(Type parent, Type toCheck)
{
return toCheck.BaseType.IsGenericType && parent == toCheck.BaseType.GetGenericTypeDefinition();
}
...
Console.WriteLine(IsDirectSubclassOfRawGeneric(typeof(HtSecureInstancePage<>), typeof(InstancePage)));

How to reflect an interfaced type<t> at runtime

I have multiple data-points and an associated data-processor for each.
public interface IDataPointProcessor<T> where T : DataPointInputBase
{
DataPointOutputBase GetOutput(T input);
}
I load a list of data points from a file and wish to process them using its single associated processor.
foreach (DataPointInputBase item in input.DataPoints)
{
//assuming item coming in is of type 'X' how do I get correct processor
var type = typeof(IDataPointProcessor<X>);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p) && !p.IsAbstract);
IDataPointProcessor<X> matchedType = ??
}
How do I solve for 'X' so I can instantiate it and process the input?
Update #1
Combining answers from below from Slava and Lucky I get the following, but it throws an exception - 'Object does not match target type.' even though it all seems to match up ok in debugger. Is it possible to cast as IDataPointProcessor<> and call interface method cleanly, ie: instance.GetOutput(item);
foreach (DataPointInputBase item in input.DataPoints)
{
Type typeGenArg = item.GetType();
Type typeInterfaceGen = typeof(IDataPointProcessor<>).MakeGenericType(typeGenArg);
Type type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => typeInterfaceGen.IsAssignableFrom(x) && !x.IsAbstract)
.FirstOrDefault();
Type genericType = typeof(IDataPointProcessor<>);
Type dependedGenericType = genericType.MakeGenericType(typeof(DataPointInputBase));
var method = dependedGenericType.GetMethod("GetOutput");
var instance = Activator.CreateInstance(type);
//currently throws:System.Reflection.TargetException: 'Object does not match target type.'
var result = method.Invoke(instance, new object[] { item });
//Ideally I want to do this and avoid the magic strings etc
//var temp_output = instance.GetOutput(item);
}
Update #2
To keep things moving I've hard coded the type 'Age_Input' to validate the thing works. What am I missing to call the hard coded bit dynamically?
I should be able to cast instance to IDataPointProcessor<IDataPointInput> and call GetOutput() on the interface
foreach (IDataPointInput item in input.DataPoints)
{
Type typeGenArg = item.GetType();
Type typeInterfaceGen = typeof(IDataPointProcessor<>).MakeGenericType(typeGenArg);
Type type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => typeInterfaceGen.IsAssignableFrom(x) && !x.IsAbstract)
.FirstOrDefault();
Type genericType = typeof(IDataPointProcessor<>);
Type dependedGenericType = genericType.MakeGenericType(typeof(IDataPointInput));
var instance = Activator.CreateInstance(type);
if (instance is IDataPointProcessor<Age_Input>)//hard-coded
{
var processor = instance as IDataPointProcessor<Age_Input>;
Age_Input temp = item as Age_Input;
var result = processor.GetOutput(temp);
}
if (instance is DataPointProcessorBase<DataPointInputBase>)
{
//false
}
if (instance is IDataPointProcessor<DataPointInputBase>)
{
//false
}
if (instance is IDataPointProcessor<IDataPointInput>)
{
//false - shouldn't this work?
}
}
Age_Input is a trivial class, inheriting from a dumb base class and an empty interface
public class Age_Input : DataPointInputBase, IDataPointInput
{
public int AgeExact { get; set; }
}
public class DataPointInputBase : IDataPointInput
{
}
public interface IDataPointInput
{
}
Processor class is similarly simple
public abstract class DataPointProcessorBase<T> : IDataPointProcessor<T> where T : IDataPointInput, new()
{
//public abstract DataPointOutputBase GetOutput(DataPointInputBase input);
public abstract DataPointOutputBase GetOutput(T input);
}
public interface IDataPointInput
{
}
public interface IDataPointProcessor<IDataPointInput>
{
DataPointOutputBase GetOutput(IDataPointInput input);
}
Firstly, you should make covariant your interface like this.
public interface IDataPointProcessor<in T> where T : DataPointInputBase
{
DataPointOutputBase GetOutput(T input);
}
You should retrieve types which is implemented by IDataPointProcessor<>, then you should create the instance of retrieved type and invoke the method of generic type.
Type genericType = typeof(IDataPointProcessor<>);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => genericType.IsAssignableFrom(p) && !p.IsAbstract).ToList();
var dependedGenericType = genericType.MakeGenericType(typeof(DataPointInputBase));
var method = dependedGenericType.GetMethod("GetOutput");
var instance = Activator.CreateInstance(types[0]);
method.Invoke(instance, new object[] { new DataPointInputBase() });
So as is usually the case, if you can avoid Reflection you're generally better off. I traded a tiny bit of code smell for a much simpler solution.
Essentially I went back to basics and used dumb interfaces, and a helper method on the input that returned a primed instance of the corresponding processor.
Now my big reflection loop is replaced with this:
foreach (IDataPointInput item in input)
{
IDataPointProcessor processor = item.GetProcessor();
IDataPointOutput output = processor.GetOutput();
}
The code smell is this - not an issue
public override IDataPointProcessor GetProcessor()
{
return new Age_Processor(this);
}
Full code below
#region Interfaces
public interface IDataPointProcessor
{
IDataPointOutput GetOutput();
}
public interface IDataPointInput
{
IDataPointProcessor GetProcessor();
}
public interface IDataPointOutput
{
List<string> DebugStrings { get; set; }
}
#endregion
#region Base Classes
public abstract class DataPointProcessorBase : IDataPointProcessor
{
public abstract IDataPointOutput GetOutput();
}
public abstract class DataPointInputBase : IDataPointInput
{
public abstract IDataPointProcessor GetProcessor();
}
public abstract class DataPointOutputBase : IDataPointOutput
{
public List<string> DebugStrings { get; set; }
public DataPointOutputBase()
{
DebugStrings = new List<string>();
}
}
#endregion
public class Age_Output : DataPointOutputBase
{
}
public class Age_Input : DataPointInputBase
{
public int AgeExact { get; set; }
public override IDataPointProcessor GetProcessor()
{
return new Age_Processor(this);
}
}
public class Age_Processor : DataPointProcessorBase
{
public Age_Input Input { get; set; }
public Age_Processor(Age_Input input)
{
Input = input;
}
public override IDataPointOutput GetOutput()
{
Age_Output output = new Age_Output();
if (Input.AgeExact > 30)
{
output.DebugStrings.Add("Getting old");
}
else
{
output.DebugStrings.Add("Still young");
}
return output;
}
}
public class DecisionEngine
{
public void GetDecisions()
{
List<IDataPointInput> input = new List<IDataPointInput>();
input.Add(new Age_Input { AgeExact = 44 });
foreach (IDataPointInput item in input)
{
IDataPointProcessor processor = item.GetProcessor();
IDataPointOutput output = processor.GetOutput();
}
}
}

Get instance of a class that inherits from abstract class and have specific value in a property

I'm working on a factory to create concrete instances based in two criteria:
1) The class must inherit from an specific abstract class
2) The class must have an specific value in an overridden property
My code looks like this:
public abstract class CommandBase
{
public abstract string Prefix { get; }
}
public class PaintCommand : CommandBase
{
public override string Prefix { get; } = "P";
}
public class WalkCommand : CommandBase
{
public override string Prefix { get; } = "W";
}
class Program
{
static void Main(string[] args)
{
var paintCommand = GetInstance("P");
var walkCommand = GetInstance("W");
Console.ReadKey();
}
static CommandBase GetInstance(string prefix)
{
try
{
var currentAssembly = Assembly.GetExecutingAssembly();
var concreteType = currentAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(CommandBase)) &&
!t.IsAbstract &&
t.GetProperty("Prefix").GetValue(t).ToString() == prefix).SingleOrDefault();
if (concreteType == null)
throw new InvalidCastException($"No concrete type found for command: {prefix}");
return (CommandBase)Activator.CreateInstance(concreteType);
}
catch (Exception ex)
{
return default(CommandBase);
}
}
}
I'm getting the error:
{System.Reflection.TargetException: Object does not match target type. at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target) at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
A cleaner way is to define your own attribute to store the prefix.
[AttributeUsage(AttributeTargets.Class)]
public class CommandAttribute : Attribute
{
public String Prefix { get; set; }
public CommandAttribute(string commandPrefix)
{
Prefix = commandPrefix;
}
}
Then use them like so:
[CommandAttribute("P")]
public class PaintCommand : CommandBase
{}
[CommandAttribute("W")]
public class WalkCommand : CommandBase
{}
In reflection:
static CommandBase GetInstance(string prefix)
{
var currentAssembly = Assembly.GetExecutingAssembly();
var concreteType = currentAssembly.GetTypes().Where(commandClass => commandClass.IsDefined(typeof(CommandAttribute), false) && commandClass.GetCustomAttribute<CommandAttribute>().Prefix == prefix).FirstOrDefault();
if (concreteType == null)
throw new InvalidCastException($"No concrete type found for command: {prefix}");
return (CommandBase)Activator.CreateInstance(concreteType);
}
As spender alluded to in his comment, the reason you are getting this specific error is this line:
t.GetProperty("Prefix").GetValue(t)
Here, t is a Type variable containing a class, such as WalkCommand. You're getting the PropertyInfo object for the Prefix property on that class, then trying to use GetValue() to read the value of that property from an instance of a WalkCommand object.
The problem is that you aren't passing GetValue() an instance of the WalkCommand class, you're passing it a Type so Reflection is then throwing this exception.
There are a few of ways to deal with this:
1) Create an instance of each type on the fly, just to read its prefix (I really wouldn't recommend doing this):
var instance = currentAssembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(CommandBase)) && !t.IsAbstract)
.Select(t => new { t, i = (CommandBase)Activator.CreateInstance(t) })
.Where(x => x.t.GetProperty("Prefix").GetValue(x.i).ToString() == prefix)
.Select(x => x.i)
.SingleOrDefault();
return instance;
2) Change the whole thing over to use Attributes, such as in SwiftingDuster's answer
3) Use a static constructor to create a Dictionary that maps the string prefices to the concrete types. Reflection is expensive, and the classes aren't going to change (unless you're dynamically loading assemblies), so do it once.
We could do this by (ab)using my earlier "create an instance to throw it away" code, so we're still creating an instance of each class just to read the property, but at least we only do it once:
static Dictionary<string, Type> prefixMapping;
static Program()
{
prefixMapping = currentAssembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(CommandBase)) && !t.IsAbstract)
.Select(t => new { t, c = (CommandBase)Activator.CreateInstance(t) })
.ToDictionary(x => x.t.GetProperty("Prefix").GetValue(x.c).ToString(), x => x.t);
}
static CommandBase GetInstance(string prefix)
{
Type concreteType;
if ( prefixMapping.TryGetValue(prefix, out concreteType) )
{
return (CommandBase)Activator.CreateInstance(concreteType);
}
return default(CommandBase);
}
Note that this will throw a really horrible exception if you have multiple classes with the same prefix, and as it would be an exception in a static constructor, it'll likely explode your application. Either catch the exception (which will leave prefixMapping as null), or modify the Linq expression to only return one type for each prefix (as below).
4) Use both the Attribute method from SwiftingDuster and also the precomputation of the dictionary. This would be my preferred solution:
static Dictionary<string, Type> prefixMapping;
static Program()
{
prefixMapping = currentAssembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(CommandBase)) && t.IsDefined(typeof(CommandAttribute), false) && !t.IsAbstract)
.Select(t => new { t, p = t.GetCustomAttribute<CommandAttribute>().Prefix })
.GroupBy(x => x.p)
.ToDictionary(g => g.Key, g => g.First().t);
}
static CommandBase GetInstance(string prefix)
{
Type concreteType;
if ( prefixMapping.TryGetValue(prefix, out concreteType) )
{
return (CommandBase)Activator.CreateInstance(concreteType);
}
return default(CommandBase);
}
Hope this helps

Proper run-time construction pattern for large number of objects

What is the best way to create derived objects at run-time while adhering to LSP and always keeping the objects in a valid state.
I'm fairly new to construction patterns such as Factory and Builder and most of the examples I find are very simplistic. Here is my scenario:
I have one base class (some things left out for brevity):
public abstract BaseClass
{
public string Property1 { get; set ... null guard; }
public string Property2 { get; set ... conditional null guard; }
public virtual bool RequiresProperty2 => false;
protected BaseClass(string property1)
{
null guard
Property1 = property1;
}
}
I have 50+ derived classes. Some of which require prop2 some of which don't. The ones that require prop2 have a constructor that forces prop2 to be passed in, enforcing that all BaseClass derived objects are in a valid state upon construction. I'm also trying to adhere to LSP and I'm using Castle Windsor for dependency injection.
The solution I've come up with is to create a factory that returns a builder:
public interface IFactory
{
IBuilder Create(string type);
}
public interface IBuilder
{
IBuilder SetProperty1(string property);
IBuilder SetProperty2(string property);
BaseClass Build();
}
The concrete implementation of the factory loads all the types that inherit from BaseClass through reflection. When you call Factory.Create(...) you pass it a string which is the string name of the type you want to create. Then the factory creates a builder passing the appropriate Type to the builder's constructor. The builder looks like so:
public sealed class ConcreteBuilder : IBuilder
{
private static Type ClassType = typeof(BaseClass);
private static readonly ConcurrentDictionary<Type, Delegate>
ClassConstructors = new ConcurrentDictionary<Type, Delegate>();
private readonly Type type;
private string property1;
private string property2;
public ConcreteBuilder(Type type)
{
if (type == null) throw new ArgumentNullException(nameof(type));
if (!type.IsSubclassOf(ClassType))
{
throw new ArgumentException("Must derive from BaseClass.");
}
this.type = type;
}
public IBuilder SetProperty1(string property)
{
this.property1 = property;
return this;
}
public IBuilder SetProperty2(string property)
{
this.property2 = property;
return this;
}
public BaseClass Build()
{
var arguments = BuildArguments();
Delegate ctor;
if (ClassConstructors.TryGetValue(this.type, out ctor))
{
return (BaseClass)ctor.DynamicInvoke(arguments);
}
return (BaseClass)GetConstructor(arguments).DynamicInvoke(arguments);
}
private object[] BuildArguments()
{
var args = new List<object>();
if (!string.IsNullOrEmpty(this.property1))
{
args.Add(this.property1);
}
if (!string.IsNullOrEmpty(this.property2))
{
args.Add(this.property2);
}
return args.ToArray();
}
private Delegate GetConstructor(object[] arguments)
{
var constructors = this.type.GetConstructors();
foreach (var constructor in constructors)
{
var parameters = constructor.GetParameters();
var parameterTypes = parameters.Select(p => p.ParameterType).ToArray();
if (parameterTypes.Length != arguments.Length + 1) continue;
if (!parameterTypes.Zip(arguments, TestArgumentForParameter).All(x => x))
{
continue;
}
var parameterExpressions = parameters.Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
var callConstructor = Expression.New(constructor, parameterExpressions);
var ctor = Expression.Lambda(callConstructor, parameterExpressions).Compile();
ClassConstructors.TryAdd(this.type, ctor);
return ctor;
}
throw new MissingMethodException("No constructor found");
}
private static bool TestArgumentForParameter(Type parameterType, object argument)
{
return (argument == null && !parameterType.IsValueType) || (parameterType.IsInstanceOfType(argument));
}
}
Is there a better way to do this? Am I going about this the right way? I know DynamicInvoke is slow. Should I be going about this differently?

Dynamically load a class without specifying the assembly [duplicate]

Using reflection, how can I get all types that implement an interface with C# 3.0/.NET 3.5 with the least code, and minimizing iterations?
This is what I want to re-write:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
Mine would be this in c# 3.0 :)
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Basically, the least amount of iterations will always be:
loop assemblies
loop types
see if implemented.
This worked for me. It loops though the classes and checks to see if they are derrived from myInterface
foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) {
//do stuff
}
I appreciate this is a very old question but I thought I would add another answer for future users as all the answers to date use some form of Assembly.GetTypes.
Whilst GetTypes() will indeed return all types, it does not necessarily mean you could activate them and could thus potentially throw a ReflectionTypeLoadException.
A classic example for not being able to activate a type would be when the type returned is derived from base but base is defined in a different assembly from that of derived, an assembly that the calling assembly does not reference.
So say we have:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
If in ClassC which is in AssemblyC we then do something as per accepted answer:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Then it will throw a ReflectionTypeLoadException.
This is because without a reference to AssemblyA in AssemblyC you would not be able to:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
In other words ClassB is not loadable which is something that the call to GetTypes checks and throws on.
So to safely qualify the result set for loadable types then as per this Phil Haacked article Get All Types in an Assembly and Jon Skeet code you would instead do something like:
public static class TypeLoaderExtensions {
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) {
if (assembly == null) throw new ArgumentNullException("assembly");
try {
return assembly.GetTypes();
} catch (ReflectionTypeLoadException e) {
return e.Types.Where(t => t != null);
}
}
}
And then:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}
To find all types in an assembly that implement IFoo interface:
var results = from type in someAssembly.GetTypes()
where typeof(IFoo).IsAssignableFrom(type)
select type;
Note that Ryan Rinaldi's suggestion was incorrect. It will return 0 types. You cannot write
where type is IFoo
because type is a System.Type instance, and will never be of type IFoo. Instead, you check to see if IFoo is assignable from the type. That will get your expected results.
Also, Adam Wright's suggestion, which is currently marked as the answer, is incorrect as well, and for the same reason. At runtime, you'll see 0 types come back, because all System.Type instances weren't IFoo implementors.
Other answers here use IsAssignableFrom. You can also use FindInterfaces from the System namespace, as described here.
Here's an example that checks all assemblies in the currently executing assembly's folder, looking for classes that implement a certain interface (avoiding LINQ for clarity).
static void Main() {
const string qualifiedInterfaceName = "Interfaces.IMyInterface";
var interfaceFilter = new TypeFilter(InterfaceFilter);
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var di = new DirectoryInfo(path);
foreach (var file in di.GetFiles("*.dll")) {
try {
var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
foreach (var type in nextAssembly.GetTypes()) {
var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
if (myInterfaces.Length > 0) {
// This class implements the interface
}
}
} catch (BadImageFormatException) {
// Not a .net assembly - ignore
}
}
}
public static bool InterfaceFilter(Type typeObj, Object criteriaObj) {
return typeObj.ToString() == criteriaObj.ToString();
}
You can set up a list of interfaces if you want to match more than one.
loop through all loaded assemblies, loop through all their types, and check if they implement the interface.
something like:
Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
foreach (Type t in asm.GetTypes()) {
if (ti.IsAssignableFrom(t)) {
// here's your type in t
}
}
}
This worked for me (if you wish you could exclude system types in the lookup):
Type lookupType = typeof (IMenuItem);
IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where(
t => lookupType.IsAssignableFrom(t) && !t.IsInterface);
I see so many overcomplicated answers here and people always tell me that I tend to overcomplicate things. Also using IsAssignableFrom method for the purpose of solving OP problem is wrong!
Here is my example, it selects all assemblies from the app domain, then it takes flat list of all available types and checks every single type's list of interfaces for match:
public static IEnumerable<Type> GetImplementingTypes(this Type itype)
=> AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes())
.Where(t => t.GetInterfaces().Contains(itype));
Other answer were not working with a generic interface.
This one does, just replace typeof(ISomeInterface) by typeof (T).
List<string> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
.Where(x => typeof(ISomeInterface).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
.Select(x => x.Name).ToList();
So with
AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
we get all the assemblies
!x.IsInterface && !x.IsAbstract
is used to exclude the interface and abstract ones and
.Select(x => x.Name).ToList();
to have them in a list.
All the answers posted thus far either take too few or too many assemblies into account. You need to only inspect the assemblies that reference the assembly containing the interface. This minimizes the number of static constructors being run unnecessarily and save a huge amount of time and possibly unexpected side effects in the case of third party assemblies.
public static class ReflectionUtils
{
public static bool DoesTypeSupportInterface(Type type, Type inter)
{
if (inter.IsAssignableFrom(type))
return true;
if (type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == inter))
return true;
return false;
}
public static IEnumerable<Assembly> GetReferencingAssemblies(Assembly assembly)
{
return AppDomain
.CurrentDomain
.GetAssemblies().Where(asm => asm.GetReferencedAssemblies().Any(asmName => AssemblyName.ReferenceMatchesDefinition(asmName, assembly.GetName())));
}
public static IEnumerable<Type> TypesImplementingInterface(Type desiredType)
{
var assembliesToSearch = new Assembly[] { desiredType.Assembly }
.Concat(GetReferencingAssemblies(desiredType.Assembly));
return assembliesToSearch.SelectMany(assembly => assembly.GetTypes())
.Where(type => DoesTypeSupportInterface(type, desiredType));
}
public static IEnumerable<Type> NonAbstractTypesImplementingInterface(Type desiredType)
{
return TypesImplementingInterface(desiredType).Where(t => !t.IsAbstract);
}
}
Edit: I've just seen the edit to clarify that the original question was for the reduction of iterations / code and that's all well and good as an exercise, but in real-world situations you're going to want the fastest implementation, regardless of how cool the underlying LINQ looks.
Here's my Utils method for iterating through the loaded types. It handles regular classes as well as interfaces, and the excludeSystemTypes option speeds things up hugely if you are looking for implementations in your own / third-party codebase.
public static List<Type> GetSubclassesOf(this Type type, bool excludeSystemTypes) {
List<Type> list = new List<Type>();
IEnumerator enumerator = Thread.GetDomain().GetAssemblies().GetEnumerator();
while (enumerator.MoveNext()) {
try {
Type[] types = ((Assembly) enumerator.Current).GetTypes();
if (!excludeSystemTypes || (excludeSystemTypes && !((Assembly) enumerator.Current).FullName.StartsWith("System."))) {
IEnumerator enumerator2 = types.GetEnumerator();
while (enumerator2.MoveNext()) {
Type current = (Type) enumerator2.Current;
if (type.IsInterface) {
if (current.GetInterface(type.FullName) != null) {
list.Add(current);
}
} else if (current.IsSubclassOf(type)) {
list.Add(current);
}
}
}
} catch {
}
}
return list;
}
It's not pretty, I'll admit.
Even better when choosing the Assembly location. Filter most of the assemblies if you know all your implemented interfaces are within the same Assembly.DefinedTypes.
// We get the assembly through the base class
var baseAssembly = typeof(baseClass).GetTypeInfo().Assembly;
// we filter the defined classes according to the interfaces they implement
var typeList = baseAssembly.DefinedTypes.Where(type => type.ImplementedInterfaces.Any(inter => inter == typeof(IMyInterface))).ToList();
By Can Bilgin
There's no easy way (in terms of performance) to do what you want to do.
Reflection works with assemblys and types mainly so you'll have to get all the types of the assembly and query them for the right interface. Here's an example:
Assembly asm = Assembly.Load("MyAssembly");
Type[] types = asm.GetTypes();
Type[] result = types.where(x => x.GetInterface("IMyInterface") != null);
That will get you all the types that implement the IMyInterface in the Assembly MyAssembly
There are many valid answers already but I'd like to add anther implementation as a Type extension and a list of unit tests to demonstrate different scenarios:
public static class TypeExtensions
{
public static IEnumerable<Type> GetAllTypes(this Type type)
{
var typeInfo = type.GetTypeInfo();
var allTypes = GetAllImplementedTypes(type).Concat(typeInfo.ImplementedInterfaces);
return allTypes;
}
private static IEnumerable<Type> GetAllImplementedTypes(Type type)
{
yield return type;
var typeInfo = type.GetTypeInfo();
var baseType = typeInfo.BaseType;
if (baseType != null)
{
foreach (var foundType in GetAllImplementedTypes(baseType))
{
yield return foundType;
}
}
}
}
This algorithm supports the following scenarios:
public static class GetAllTypesTests
{
public class Given_A_Sample_Standalone_Class_Type_When_Getting_All_Types
: Given_When_Then_Test
{
private Type _sut;
private IEnumerable<Type> _expectedTypes;
private IEnumerable<Type> _result;
protected override void Given()
{
_sut = typeof(SampleStandalone);
_expectedTypes =
new List<Type>
{
typeof(SampleStandalone),
typeof(object)
};
}
protected override void When()
{
_result = _sut.GetAllTypes();
}
[Fact]
public void Then_It_Should_Return_The_Right_Type()
{
_result.Should().BeEquivalentTo(_expectedTypes);
}
}
public class Given_A_Sample_Abstract_Base_Class_Type_When_Getting_All_Types
: Given_When_Then_Test
{
private Type _sut;
private IEnumerable<Type> _expectedTypes;
private IEnumerable<Type> _result;
protected override void Given()
{
_sut = typeof(SampleBase);
_expectedTypes =
new List<Type>
{
typeof(SampleBase),
typeof(object)
};
}
protected override void When()
{
_result = _sut.GetAllTypes();
}
[Fact]
public void Then_It_Should_Return_The_Right_Type()
{
_result.Should().BeEquivalentTo(_expectedTypes);
}
}
public class Given_A_Sample_Child_Class_Type_When_Getting_All_Types
: Given_When_Then_Test
{
private Type _sut;
private IEnumerable<Type> _expectedTypes;
private IEnumerable<Type> _result;
protected override void Given()
{
_sut = typeof(SampleChild);
_expectedTypes =
new List<Type>
{
typeof(SampleChild),
typeof(SampleBase),
typeof(object)
};
}
protected override void When()
{
_result = _sut.GetAllTypes();
}
[Fact]
public void Then_It_Should_Return_The_Right_Type()
{
_result.Should().BeEquivalentTo(_expectedTypes);
}
}
public class Given_A_Sample_Base_Interface_Type_When_Getting_All_Types
: Given_When_Then_Test
{
private Type _sut;
private IEnumerable<Type> _expectedTypes;
private IEnumerable<Type> _result;
protected override void Given()
{
_sut = typeof(ISampleBase);
_expectedTypes =
new List<Type>
{
typeof(ISampleBase)
};
}
protected override void When()
{
_result = _sut.GetAllTypes();
}
[Fact]
public void Then_It_Should_Return_The_Right_Type()
{
_result.Should().BeEquivalentTo(_expectedTypes);
}
}
public class Given_A_Sample_Child_Interface_Type_When_Getting_All_Types
: Given_When_Then_Test
{
private Type _sut;
private IEnumerable<Type> _expectedTypes;
private IEnumerable<Type> _result;
protected override void Given()
{
_sut = typeof(ISampleChild);
_expectedTypes =
new List<Type>
{
typeof(ISampleBase),
typeof(ISampleChild)
};
}
protected override void When()
{
_result = _sut.GetAllTypes();
}
[Fact]
public void Then_It_Should_Return_The_Right_Type()
{
_result.Should().BeEquivalentTo(_expectedTypes);
}
}
public class Given_A_Sample_Implementation_Class_Type_When_Getting_All_Types
: Given_When_Then_Test
{
private Type _sut;
private IEnumerable<Type> _expectedTypes;
private IEnumerable<Type> _result;
protected override void Given()
{
_sut = typeof(SampleImplementation);
_expectedTypes =
new List<Type>
{
typeof(SampleImplementation),
typeof(SampleChild),
typeof(SampleBase),
typeof(ISampleChild),
typeof(ISampleBase),
typeof(object)
};
}
protected override void When()
{
_result = _sut.GetAllTypes();
}
[Fact]
public void Then_It_Should_Return_The_Right_Type()
{
_result.Should().BeEquivalentTo(_expectedTypes);
}
}
public class Given_A_Sample_Interface_Instance_Type_When_Getting_All_Types
: Given_When_Then_Test
{
private Type _sut;
private IEnumerable<Type> _expectedTypes;
private IEnumerable<Type> _result;
class Foo : ISampleChild { }
protected override void Given()
{
var foo = new Foo();
_sut = foo.GetType();
_expectedTypes =
new List<Type>
{
typeof(Foo),
typeof(ISampleChild),
typeof(ISampleBase),
typeof(object)
};
}
protected override void When()
{
_result = _sut.GetAllTypes();
}
[Fact]
public void Then_It_Should_Return_The_Right_Type()
{
_result.Should().BeEquivalentTo(_expectedTypes);
}
}
sealed class SampleStandalone { }
abstract class SampleBase { }
class SampleChild : SampleBase { }
interface ISampleBase { }
interface ISampleChild : ISampleBase { }
class SampleImplementation : SampleChild, ISampleChild { }
}
I got exceptions in the linq-code so I do it this way (without a complicated extension):
private static IList<Type> loadAllImplementingTypes(Type[] interfaces)
{
IList<Type> implementingTypes = new List<Type>();
// find all types
foreach (var interfaceType in interfaces)
foreach (var currentAsm in AppDomain.CurrentDomain.GetAssemblies())
try
{
foreach (var currentType in currentAsm.GetTypes())
if (interfaceType.IsAssignableFrom(currentType) && currentType.IsClass && !currentType.IsAbstract)
implementingTypes.Add(currentType);
}
catch { }
return implementingTypes;
}
OfType Linq method can be used exactly for this kind of scenarios:
https://learn.microsoft.com/fr-fr/dotnet/api/system.linq.enumerable.oftype?view=netframework-4.8
If it helps anyone, this is what I'm using to make some of my unit tests easier :)
public static Type GetInterfacesImplementation(this Type type)
{
return type.Assembly.GetTypes()
.Where(p => type.IsAssignableFrom(p) && !p.IsInterface)
.SingleOrDefault();
}
public IList<T> GetClassByType<T>()
{
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.ToList(p => typeof(T)
.IsAssignableFrom(p) && !p.IsAbstract && !p.IsInterface)
.SelectList(c => (T)Activator.CreateInstance(c));
}
You could use some LINQ to get the list:
var types = from type in this.GetType().Assembly.GetTypes()
where type is ISomeInterface
select type;
But really, is that more readable?

Categories

Resources