Let's say I have a Type called type.
I want to determine if I can do this with my type (without actually doing this to each type):
If type is System.Windows.Point then I could do this:
Point point1 = new Point();
However if type is System.Environment then this will not fly:
Environment environment1 = new Environment(); //wrong
So if I am iterating through every visible type in an assembly how do I skip all the types that will fail to create an instance like the second one? I'm kind of new to reflection so I'm not that great with the terminology yet. Hopefully what I'm trying to do here is pretty clear.
static classes are declared abstract and sealed at the IL level. So, you can check IsAbstract property to handle both abstract classes and static classes in one go (for your use case).
However, abstract classes are not the only types you can't instantiate directly. You should check for things like interfaces (without the CoClass attribute) and types that don't have a constructor accessible by the calling code.
type.IsAbstract && type.IsSealed
This would be a sufficient check for C# since an abstract class cannot be sealed or static in C#. However, you'll need to be careful when dealing with CLR types from other languages.
you can search for public contructors like this,
Type t = typeof(Environment);
var c = t.GetConstructors(BindingFlags.Public);
if (!t.IsAbstract && c.Length > 0)
{
//You can create instance
}
Or if you only interested in parameterless constructor you can use
Type t = typeof(Environment);
var c = t.GetConstructor(Type.EmptyTypes);
if (c != null && c.IsPublic && !t.IsAbstract )
{
//You can create instance
}
Type t = typeof(System.GC);
Console.WriteLine(t.Attributes);
TypeAttributes attribForStaticClass = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class |
TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit;
Console.WriteLine((t.Attributes == attribForStaticClass));
I guess, this should work.
This is a way to get all public contstuctors of all types in an assembly.
var assembly = AppDomain.CurrentDomain.GetAssemblies()[0]; // first assembly for demo purposes
var types = assembly.GetTypes();
foreach (var type in types)
{
var constructors = type.GetConstructors();
}
Related
I am currently trying to get a very specific set of methods but am failing to do so.
I need to get all methods that match a certain signature from all classes that implement a certain interface.
What I've got so far is:
IEnumerable<System.Type> classes = Assembly.GetAssembly(typeof(IActionMethod)).GetTypes().Where(x => x.GetInterface("IActionMethod") != null);
MethodInfo[] methods;
List<MethodInfo> relevant;
ParameterInfo[] parameters;
foreach(System.Type cls in classes)
{
methods = cls.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
relevant.Clear();
for(int i = 0; i < methods.Length; i++)
{
parameters = methods[i].GetParameters();
if(parameters.Length == 1 && parameters[0].GetType() == typeof(GameObject) && methods[i].ReturnType == typeof(void))
relevant.Add(methods[i]);
}
}
This code already fails at GetMethods(..)which is not returning any methods.
What I do not understand is, that I am able to receive all public methods of any of the relevant classes if they do not implement the interface.
The interface itself does not contain anything, I am only using it to "mark" the relevant classes, as I could not come up with any other solution to do so.
Can anyone tell me why the interface is rendering GetMethodsuseless or point me to the error in my code above?
I suspect this is the problem:
foreach(System.Type cls in classes)
{
methods = cls.GetType().GetMethods(...)
cls is already a Type, so calling GetType() on it will return System.Type (or a subclass). I suspect you just want:
foreach(System.Type cls in classes)
{
methods = cls.GetMethods(...)
It's also unclear why you're clearing the relevant list on each iteration. It means the only entries at the end will be the ones from the last class you look at - are you sure that's what you want?
As an aside, Microsoft recommends not using 'marker interfaces' and instead suggests using attributes. You can then use Memberinfo.IsDefined() instead of checking for the interface.
To find all classes that implements specific interface, you should use rather IsAssignableFrom because your code will omit classed that implement your interface indirectly:
Type interfaceType = typeof(IActionMethod);
Assembly assembly = Assembly.GetAssembly(interfaceType );
IEnumerable<System.Type> classes = assembly.GetTypes().Where(x => interfaceType.IsAssignableFrom(x));
Then, you probably want to call:
methods = cls.GetMethods(...)
because cls is your desired type, you are currently searching in its Type.
Suppose I have three classes A,B and C generated via emit/reflection abilities of .NET framework, and emmiting object in following manner:
class A
{
B someField1;
C someField2;
}
I need to initialize someField1 and someField2 after creating object:
A someObject;
How to do this? The someObject type is object but I have no idea how to cast it to A type created dynamically and enter fields and initialize it. Thank's in advance for help.
You cannot cast to a dynamically created type in your code, as the compiler cannot know that type.
You can do what you need in a couple of ways:
// 1 - using reflection
// these will actually be your dynamically created objects...
object a = CreateA();
object b = CreateB();
System.Reflection.FieldInfo someField1 = a.GetType().GetField(
"someField1",
BindingFlags.Instance | BindingFlags.NonPublic);
someField1.SetValue(a, b);
or
// 2 - using dynamic (C# 4)
dynamic a = CreateA();
dynamic b = CreateB();
a.someField1 = b;
Just a follow up to Paolo...
If someField1 and someField2 are known at compile time (which appears to be the case) then it would be advisable to have them declared in an interface that your dynamically created class implements. That way you can simply case someObj to the interface type.
interface IObjectWithFields
{
B someField;
C someField;
}
object a = CreateA();
((IObjectWIthFields)a).someField1 = CreateB();
For the first time ever I've actually needed to do assembly scanning myself manually. I came across C# - how enumerate all classes with custom class attribute? which set me up with
var typesWithMyAttribute =
(from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
let attributes = type.GetCustomAttributes(typeof(SomeAttribute), true)
where attributes != null && attributes.Length > 0
select new { Type = type, Attributes = attributes.Cast<SomeAttribute>() })
.ToList();
Which was simple enough to expand out to the method level
var methodsWithAttributes =
(from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
from method in type.GetMethods()
let attributes = method.GetCustomAttributes(typeof(SomeAttribute), true)
where attributes != null && attributes.Length > 0
select new { Type = type, Method = method,
Attributes = attributes.Cast<SomeAttribute>() })
.ToList();
Should I try to combine these 2 to do this in a single scan, or is that just falling into early optimization? (the scanning will only execute on app start)
Is there something different that would be more optimal to do for the scanning of the methods since there are far more methods than types in assemblies?
Reflection is very slow...
I think you've go the basics there. I'd recommend you change your code slightly to avoid the extra full scan taking place.
If you have to do this more than once, I'd also recommend you consider caching the results for whatever period of time is appropriate.
Sorta like this pseudo-code:
... (optional caches) ...
IDictionary<Type, IEnumerable<Attributes>> typeAttributeCache = new ...
IDictionary<MethodInfo, IEnumerable<Attributes>> methodAttributeCache = new ...
... (in another method or class) ...
foreach assembly in GetAssemblies()
foreach type in assembly.GetTypes()
typeAttributes = typeAttributeCache.TryGet(...) // you know the correct syntax, trying to be brief
if (typeAttributes is null)
typeAttributes = type.GetCustomAttributes().OfType<TypeImLookingFor>();
typeAttributeCache[type] = typeAttributes;
foreach methodInfo in type.GetMethods()
methodAttributes = methodAttributeCache.TryGet(...) // same as above
if (methodAttributes is null)
methodAttributes = methodInfo.GetCustomAttributes().OfType<TypeImLookingFor>();
methodAttributeCache[type] = methodAttributes;
// do what you need to do
I think you can optimize this but it depends on how the attributes are placed on methods and types. If you know that all of your types and/or methods with special attribute are defined in particular assemblies you can scan only these assemblies.
Also you could define some methods, like:
- IEnumerable<Type> GetAllTypesFromAssemblyByAttribute<TAttribute>(Assembly assembly) where TAttribute : Attribute
- IEnumerable<MethodInfo> GetAllMethodsFromTypeByAttribute<TAttribute>(Type type) where TAttribute : Attribute
and use these methods in your main scanning method.
So your result scan method could look like:
private void ScanAndDoSmth<TAttribute>(IEnumerable<Assembly> assemblies)
where TAttribute : Attribute
{
var result =
from assembly in assemblies
from type in GetAllTypesFromAssemblyByAttribute<TAttribute>(assembly)
let attributes = type.GetCustomAttributes(typeof(TAttribute), true)
where attributes != null && attributes.Length > 0
select new { Type = type, Attributes = attributes.Cast<TAttribute>();
}
I'd like to check if a type that is known at runtime provides a parameterless constructor. The Type class did not yield anything promising, so I'm assuming I have to use reflection?
The Type class is reflection. You can do:
Type theType = myobject.GetType(); // if you have an instance
// or
Type theType = typeof(MyObject); // if you know the type
var constructor = theType.GetConstructor(Type.EmptyTypes);
It will return null if a parameterless constructor does not exist.
If you also want to find private constructors, use the slightly longer:
var constructor = theType.GetConstructor(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
null, Type.EmptyTypes, null);
There's a caveat for value types, which aren't allowed to have a default constructor. You can check if you have a value type using the Type.IsValueType property, and create instances using Activator.CreateInstance(Type);
type.GetConstructor(Type.EmptyTypes) != null
would fail for structs. Better to extend it:
public static bool HasDefaultConstructor(this Type t)
{
return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}
Succeeds since even enums have default parameterless constructor. Also slightly speeds up for value types since the reflection call is not made.
Yes, you have to use Reflection. But you already do that when you use GetType()
Something like:
var t = x.GetType();
var c = t.GetConstructor(new Type[0]);
if (c != null) ...
This should work:
myClass.GetType().GetConstructors()
.All(c=>c.GetParameters().Length == 0)
Depending on your situation, you could also use a generic type restriction:
public void DoSomethingWith<T>(T myObject) where T:new() {...}
The above method declaration will restrict the parameter type to any Object that can be instantiated with a parameterless constructor. The advantage here is that the compiler will catch any attempt to use the method with a class that doesn't have a parameterless constructor, so as long as the type is known SOMEWHERE at compile-time, this will work and will alert you to a problem earlier.
Of course if the type really is known only at runtime (i.e. you're using Activator.CreateInstance() to instantiate an object based on a string or a constructed Type) then this won't help you. I generally use reflection as the absolute last option, because once you've gone to dynamic land you pretty much have to stay in dynamic land; it's usually difficult or even messier to dynamically instantiate something and then start dealing with it statically.
I needed to count constructors with only optional parameters the same as true parameter-less constructors. To do this:
myClass.GetType().GetConstructors()
.All(c => c.GetParameters().Length == 0 || c.GetParameters().All(p => p.IsOptional))
If anyone is interested in an "official" version, the following was found via .NET Reflector:
from: System.Activities.Presentation.TypeUtilities
in System.Activities.Presentation.dll, Version=4.0.0.0
public static bool CanCreateInstanceUsingDefaultConstructor(this Type t) =>
t.IsValueType || !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;
Notice the check for t.IsAbstract, which is not mentioned elsewhere on this page.
You can also expand the GetConstructor call out as follows, if you feel like micro-optimizing away one stack frame:
…t.GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Type.EmptyTypes, null)…
Yes, you have to use reflection.
object myObject = new MyType();
Type type = myObject.GetType();
ConstructorInfo conInfo = type.GetConstructor(new Type[0]);
To get the one that has more optional parameters or an empty constructor at all, use:
typeof(myClass)
.GetConstructors()
.OrderBy(x => x.GetParameters().Length - x.GetParameters().Count(p => p.IsOptional))
.FirstOrDefault();
Under a given namespace, I have a set of classes which implement an interface. Let's call it ISomething. I have another class (let's call it CClass) which knows about ISomething but doesn't know about the classes which implement that interface.
I would like that CClass to look for all the implementation of ISomething, instantiate an instance of it and execute the method.
Does anybody have an idea on how to do that with C# 3.5?
A working code-sample:
var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetInterfaces().Contains(typeof(ISomething))
&& t.GetConstructor(Type.EmptyTypes) != null
select Activator.CreateInstance(t) as ISomething;
foreach (var instance in instances)
{
instance.Foo(); // where Foo is a method of ISomething
}
Edit Added a check for a parameterless constructor so that the call to CreateInstance will succeed.
You can get a list of loaded assemblies by using this:
Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies()
From there, you can get a list of types in the assembly (assuming public types):
Type[] types = assembly.GetExportedTypes();
Then you can ask each type whether it supports that interface by finding that interface on the object:
Type interfaceType = type.GetInterface("ISomething");
Not sure if there is a more efficient way of doing this with reflection.
A example using Linq:
var types =
myAssembly.GetTypes()
.Where(m => m.IsClass && m.GetInterface("IMyInterface") != null);
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
if (t.GetInterface("ITheInterface") != null)
{
ITheInterface executor = Activator.CreateInstance(t) as ITheInterface;
executor.PerformSomething();
}
}
You could use something like the following and tailor it to your needs.
var _interfaceType = typeof(ISomething);
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = GetType().GetNestedTypes();
foreach (var type in types)
{
if (_interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface)
{
ISomething something = (ISomething)currentAssembly.CreateInstance(type.FullName, false);
something.TheMethod();
}
}
This code could use some performance enhancements but it's a start.
Maybe we should go this way
foreach ( var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>() )
instance.Execute();