What is the overhead of reflection in GetMethods - c#

I just refactored a common piece of code in several parsers I have written.
The code is used to automatically discover method implementations and it comes in quite handy to extend the existing parsers or to use more DRY code (especially I am working on this project alone):
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class CallableAttribute : Attribute
{
public CallableAttribute()
: this(true)
{
// intentionally blank
}
private CallableAttribute(bool isCallable)
{
Callable = isCallable;
}
public bool Callable { get; private set; }
}
public class DynamicCallableMethodTable<TClass, THandle>
where THandle : class
{
private readonly IDictionary<string, THandle> _table = new Dictionary<string, THandle>();
public DynamicCallableMethodTable(TClass instance, Func<string, string> nameMangler,
BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance)
{
var attributeType = typeof(CallableAttribute);
var classType = typeof(TClass);
var callableMethods = from methodInfo in classType.GetMethods(bindingFlags)
from CallableAttribute a in methodInfo.GetCustomAttributes(attributeType, false)
where a.Callable
select methodInfo;
foreach (var method in callableMethods)
_table[nameMangler(method.Name)] = method.CastToDelegate<THandle>(instance);
}
public bool TryGetMethod(string key, out THandle handle)
{
return _table.TryGetValue(key, out handle);
}
}
public static class MethodEx
{
public static TDelegate CastToDelegate<TDelegate>(this MethodInfo method, object receiver)
where TDelegate : class
{
return Delegate.CreateDelegate(typeof(TDelegate), receiver, method, true) as TDelegate;
}
}
Now I want to use this code in a class which might be created and destroyed frequently:
class ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived
{
private DynamicCallableMethodTable<string, TSomeDelegate> _table = ...
public ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived()
{
_table = new DynamicCallableMethodTable<string, TSomeDelegate>(this, ...);
}
}
so I was wandering over the overhead of GetMethods, if there is already some caching inside the .NET (4.0 can be used ...) implementation,
or if I should use caching for the discovery process.
I am really unsure how efficient the reflection calls are.

Based on the following idea of #Sergey
Yes, it's called MemberInfo cache. More on it here: msdn.microsoft.com/en-us/magazine/cc163759.aspx – Sergey
I pulled out the static code into a static class, its based on the assumption that a generic static class field will have its own slot (even though it does not use the generic parameter?).
Although I am not sure if I shouldn't store the MethodInfo Directly. The RuntimeMethodHandle seems to conserve space in the long run.
static class ReflectionMethodCache<TClass>
{
/// <summary>
/// this field gets a different slot for every usage of this generic static class
/// http://stackoverflow.com/questions/2685046/uses-for-static-generic-classes
/// </summary>
private static readonly ConcurrentDictionary<BindingFlags, IList<RuntimeMethodHandle>> MethodHandles;
static ReflectionMethodCache()
{
MethodHandles = new ConcurrentDictionary<BindingFlags, IList<RuntimeMethodHandle>>(2, 5);
}
public static IEnumerable<RuntimeMethodHandle> GetCallableMethods(BindingFlags bindingFlags)
{
return MethodHandles.GetOrAdd(bindingFlags, RuntimeMethodHandles);
}
public static List<RuntimeMethodHandle> RuntimeMethodHandles(BindingFlags bindingFlags)
{
return (from methodInfo in typeof (TClass).GetMethods(bindingFlags)
from CallableAttribute a in
methodInfo.GetCustomAttributes(typeof (CallableAttribute), false)
where a.Callable
select methodInfo.MethodHandle).ToList();
}
}
public class DynamicCallableMethodTable<TClass, THandle>
where THandle : class
{
private readonly IDictionary<string, THandle> _table = new Dictionary<string, THandle>();
public DynamicCallableMethodTable(TClass instance, Func<string, string> nameMangler,
BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance)
{
var callableMethods = ReflectionMethodCache<TClass>.GetCallableMethods(bindingFlags);
foreach (MethodInfo methodInfo in callableMethods.Select(MethodBase.GetMethodFromHandle))
{
_table[nameMangler(methodInfo.Name)] = methodInfo.CastToDelegate<THandle>(instance);
}
}
public bool TryGetMethod(string key, out THandle handle)
{
return _table.TryGetValue(key, out handle);
}
}
public static class MethodEx
{
public static TDelegate CastToDelegate<TDelegate>(this MethodInfo method, object receiver)
where TDelegate : class
{
return Delegate.CreateDelegate(typeof(TDelegate), receiver, method, true) as TDelegate;
}
}

Related

C# Factory of classes that implement generic Interface

I have an interface defined like this:
public interface IEntitySetMgr<T> {
/// <summary>
/// The columns involved in the query. Only fields in those columns
/// will be retrieved from the db.
/// </summary>
List<ColumnInfo> Columns { get; set; }
/// <summary>
/// The number of entities found in the last query to db.
/// </summary>
int EntityCount { get; }
bool Init();
bool Synch( QueryFilter queryFilter = null );
/// <summary>
/// Retrieves the entities build from data of db.
/// </summary>
ObservableCollection<T> GetEntities();
}
I want some classes to implement that interface, and I want to be able to use a factory to register and create instances of those registered classes. I have this Factory, but seems not to compile:
public class EntitySetMgrFactory {
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private Dictionary<string, EntitySetMgrCreator<T>> _creators =
new Dictionary<string, EntitySetMgrCreator<T>>();
private static EntitySetMgrFactory _instance = null;
public static EntitySetMgrFactory Instance {
get {
if( _instance == null ) {
_instance = new EntitySetMgrFactory();
}
return _instance;
}
}
private EntitySetMgrFactory() { }
public bool registerEntitySetMgr<T>( string setName, EntitySetMgrCreator<T> creator ) {
if( !_creators.ContainsKey( setName ) ) {
_creators[setName] = creator;
return true;
}
return false;
}
public IEntitySetMgr<T> getEntitySetMgr<T>( string setName ) {
if( _creators.ContainsKey( setName ) ) {
return (IEntitySetMgr<T>)( _creators[setName] )();
}
return null;
}
}
It complains in the definition of the dictionary. If I change T by object in the dictionary it does not complains, but complains when trying to add a EntitySetMgrCreator to the dictionary, saying there is not available conversion. I try to put the explicitly the cast but does not work either.
I've seen examples that use Activator to create the instances by knowing the type beforehand and then casting the type, but I would really want to have a method that create the instance and register that method instead, so that I don't have to know each type beforehand.
I have seen something about covariants, but I think this would break my interface as I need a method for returning an observable collection of entities.
Thanks for your help.
Regards,
David.
When you write this:
private Dictionary<string, EntitySetMgrCreator<T>> _creators =
new Dictionary<string, EntitySetMgrCreator<T>>();
You don't really have a T because you define your class as EntitySetMgrFactory.
You probably have to rethink how you want to do it and what you really want to do here. You could just simply say
private Dictionary<string, object> _creators =
new Dictionary<string, object>();
Then
public IEntitySetMgr<T> getEntitySetMgr<T>( string setName ) {
if( _creators.ContainsKey( setName ) ) {
return ((EntitySetMgrCreator<T>) _creators[setName] )();
}
return null;
}
But it is not clear for me what is your goal.
Another problem with the code is that your singleton implementation is not thread safe. Please check this: http://csharpindepth.com/Articles/General/Singleton.aspx
Unfortunatly this won't work. The dictionary as you declared it needs a specific type for T. So Uno is already right. But I guess a generic factory is not what you want, as you probably want one factory that builds your generic classes for different types.
So I suggest to make the dictionary non-generic inside the factory, but keep it type safe to the outside:
public class EntitySetMgrFactory
{
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private Dictionary<string, object> _creators =
new Dictionary<string, object>();
public bool registerEntitySetMgr<T>(string setName, EntitySetMgrCreator<T> creator)
{
if(_creators.ContainsKey(setName)) return false;
_creators[setName] = creator;
return true;
}
public IEntitySetMgr<T> getEntitySetMgr<T>(string setName)
{
return _creators.ContainsKey(setName)
? (_creators[setName] as EntitySetMgrCreator<T>)?.Invoke()
: null;
}
// shortened for clarity, your constructor etc here...
}
So in getEntitySetMgr<T> I cast the object in the dictionary back to your delegate type and if this is not null, invoke the delegate and return the result.
You can't achieve this without either making the factory generic:
EntitySetMgrFactory<T> and removing the T from registerEntitySetMgr
or
making the dictionary of a non-generic type and then doing down casting at runtime.
First solution:
public class EntitySetMgrFactory<T>
{
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private readonly Dictionary<string, EntitySetMgrCreator<T>> _creators = new Dictionary<string, EntitySetMgrCreator<T>>();
private static EntitySetMgrFactory<T> _instance;
public static EntitySetMgrFactory<T> Instance => _instance ?? (_instance = new EntitySetMgrFactory<T>());
private EntitySetMgrFactory() { }
public bool registerEntitySetMgr(string setName, EntitySetMgrCreator<T> creator)
{
if (_creators.ContainsKey(setName)) return false;
_creators[setName] = creator;
return true;
}
public IEntitySetMgr<T> getEntitySetMgr<T>(string setName) => _creators.ContainsKey(setName) ? (IEntitySetMgr<T>)_creators[setName]() : null;
}
Second solution:
public class EntitySetMgrFactory
{
public delegate IEntitySetMgr<T> EntitySetMgrCreator<T>();
private readonly Dictionary<string, object> _creators = new Dictionary<string, object>();
private static EntitySetMgrFactory _instance;
public static EntitySetMgrFactory Instance => _instance ?? (_instance = new EntitySetMgrFactory());
private EntitySetMgrFactory() { }
public bool registerEntitySetMgr<T>(string setName, EntitySetMgrCreator<T> creator)
{
if (_creators.ContainsKey(setName)) return false;
_creators[setName] = creator;
return true;
}
public IEntitySetMgr<T> getEntitySetMgr<T>(string setName) => _creators.ContainsKey(setName) ? ((EntitySetMgrCreator<T>)_creators[setName])() : null;
}

Are these conditions enough to recognize an extension method in an expression tree? [duplicate]

In C# is there a technique using reflection to determine if a method has been added to a class as an extension method?
Given an extension method such as the one shown below is it possible to determine that Reverse() has been added to the string class?
public static class StringExtensions
{
public static string Reverse(this string value)
{
char[] cArray = value.ToCharArray();
Array.Reverse(cArray);
return new string(cArray);
}
}
We're looking for a mechanism to determine in unit testing that the extension method was appropriately added by the developer. One reason to attempt this is that it is possible that a similar method would be added to the actual class by the developer and, if it was, the compiler will pick that method up.
You have to look in all the assemblies where the extension method may be defined.
Look for classes decorated with ExtensionAttribute, and then methods within that class which are also decorated with ExtensionAttribute. Then check the type of the first parameter to see if it matches the type you're interested in.
Here's some complete code. It could be more rigorous (it's not checking that the type isn't nested, or that there is at least one parameter) but it should give you a helping hand.
using System;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
public static class FirstExtensions
{
public static void Foo(this string x) {}
public static void Bar(string x) {} // Not an ext. method
public static void Baz(this int x) {} // Not on string
}
public static class SecondExtensions
{
public static void Quux(this string x) {}
}
public class Test
{
static void Main()
{
Assembly thisAssembly = typeof(Test).Assembly;
foreach (MethodInfo method in GetExtensionMethods(thisAssembly,
typeof(string)))
{
Console.WriteLine(method);
}
}
static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly,
Type extendedType)
{
var query = from type in assembly.GetTypes()
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == extendedType
select method;
return query;
}
}
Based on John Skeet's answer I've created my own extension to the System.Type-type.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace System
{
public static class TypeExtension
{
/// <summary>
/// This Methode extends the System.Type-type to get all extended methods. It searches hereby in all assemblies which are known by the current AppDomain.
/// </summary>
/// <remarks>
/// Insired by Jon Skeet from his answer on http://stackoverflow.com/questions/299515/c-sharp-reflection-to-identify-extension-methods
/// </remarks>
/// <returns>returns MethodInfo[] with the extended Method</returns>
public static MethodInfo[] GetExtensionMethods(this Type t)
{
List<Type> AssTypes = new List<Type>();
foreach (Assembly item in AppDomain.CurrentDomain.GetAssemblies())
{
AssTypes.AddRange(item.GetTypes());
}
var query = from type in AssTypes
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == t
select method;
return query.ToArray<MethodInfo>();
}
/// <summary>
/// Extends the System.Type-type to search for a given extended MethodeName.
/// </summary>
/// <param name="MethodeName">Name of the Methode</param>
/// <returns>the found Methode or null</returns>
public static MethodInfo GetExtensionMethod(this Type t, string MethodeName)
{
var mi = from methode in t.GetExtensionMethods()
where methode.Name == MethodeName
select methode;
if (mi.Count<MethodInfo>() <= 0)
return null;
else
return mi.First<MethodInfo>();
}
}
}
It get's all assemblies from the current AppDomain and searches for extended methods.
Usage:
Type t = typeof(Type);
MethodInfo[] extendedMethods = t.GetExtensionMethods();
MethodInfo extendedMethodInfo = t.GetExtensionMethod("GetExtensionMethods");
The next step would be to extend System.Type with methods, which returns all Methods (also the "normal" ones with the extended ones)
This will return a list of all extension methods defined in a certain type, including the generic ones:
public static IEnumerable<KeyValuePair<Type, MethodInfo>> GetExtensionMethodsDefinedInType(this Type t)
{
if (!t.IsSealed || t.IsGenericType || t.IsNested)
return Enumerable.Empty<KeyValuePair<Type, MethodInfo>>();
var methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(m => m.IsDefined(typeof(ExtensionAttribute), false));
List<KeyValuePair<Type, MethodInfo>> pairs = new List<KeyValuePair<Type, MethodInfo>>();
foreach (var m in methods)
{
var parameters = m.GetParameters();
if (parameters.Length > 0)
{
if (parameters[0].ParameterType.IsGenericParameter)
{
if (m.ContainsGenericParameters)
{
var genericParameters = m.GetGenericArguments();
Type genericParam = genericParameters[parameters[0].ParameterType.GenericParameterPosition];
foreach (var constraint in genericParam.GetGenericParameterConstraints())
pairs.Add(new KeyValuePair<Type, MethodInfo>(parameters[0].ParameterType, m));
}
}
else
pairs.Add(new KeyValuePair<Type, MethodInfo>(parameters[0].ParameterType, m));
}
}
return pairs;
}
There's only one problem with this: The Type returned is not the same you'd expect with typeof(..), because it's a generic parameter type. In order to find all the extension methods for a given type you'll have to compare the GUID of all the base types and interfaces of the Type like:
public List<MethodInfo> GetExtensionMethodsOf(Type t)
{
List<MethodInfo> methods = new List<MethodInfo>();
Type cur = t;
while (cur != null)
{
TypeInfo tInfo;
if (typeInfo.TryGetValue(cur.GUID, out tInfo))
methods.AddRange(tInfo.ExtensionMethods);
foreach (var iface in cur.GetInterfaces())
{
if (typeInfo.TryGetValue(iface.GUID, out tInfo))
methods.AddRange(tInfo.ExtensionMethods);
}
cur = cur.BaseType;
}
return methods;
}
To be complete:
I keep a dictionary of type info objects, that I build when iterating all the types of all assemblies:
private Dictionary<Guid, TypeInfo> typeInfo = new Dictionary<Guid, TypeInfo>();
where the TypeInfo is defined as:
public class TypeInfo
{
public TypeInfo()
{
ExtensionMethods = new List<MethodInfo>();
}
public List<ConstructorInfo> Constructors { get; set; }
public List<FieldInfo> Fields { get; set; }
public List<PropertyInfo> Properties { get; set; }
public List<MethodInfo> Methods { get; set; }
public List<MethodInfo> ExtensionMethods { get; set; }
}
To clarify a point Jon glossed over... "Adding" an extension method to a class does not change the class in any way. It's just a little bit of spinning performed by the C# compiler.
So, using your example, you may write
string rev = myStr.Reverse();
but the MSIL written to the assembly will be exactly as if you had written it:
string rev = StringExtensions.Reverse(myStr);
The compiler is merely letting you fool yourself into thinking you are calling an method of String.
One reason to attempt this is that it is possible that a similar method would be added to the actual class by the developer and, if it was, the compiler will pick that method up.
Suppose an extension method void Foo(this Customer someCustomer) is defined.
Suppose, also, that Customer is modified and the method void Foo() is added.
Then, the new method on Customer will cover/hide the extension method.
The only way to call the old Foo method at that point is:
CustomerExtension.Foo(myCustomer);
void Main()
{
var test = new Test();
var testWithMethod = new TestWithExtensionMethod();
Tools.IsExtensionMethodCall(() => test.Method()).Dump();
Tools.IsExtensionMethodCall(() => testWithMethod.Method()).Dump();
}
public class Test
{
public void Method() { }
}
public class TestWithExtensionMethod
{
}
public static class Extensions
{
public static void Method(this TestWithExtensionMethod test) { }
}
public static class Tools
{
public static MethodInfo GetCalledMethodInfo(Expression<Action> expr)
{
var methodCall = expr.Body as MethodCallExpression;
return methodCall.Method;
}
public static bool IsExtensionMethodCall(Expression<Action> expr)
{
var methodInfo = GetCalledMethodInfo(expr);
return methodInfo.IsStatic;
}
}
Outputs:
False
True
This is the solution using LINQ method syntax rather than query syntax based on #Jon Skeet's answer.
public static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly, Type extendedType)
{
var methods = assembly.GetTypes()
.Where(type => type.IsSealed && !type.IsGenericType && !type.IsNested)
.SelectMany(type => type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
.Where(method => method.IsDefined(typeof(ExtensionAttribute), false) &&
method.GetParameters()[0].ParameterType == extendedType);
return methods;
}

Is it possible to have a delegate as attribute parameter?

Is it possible to have a delegate as the parameter of an attribute?
Like this:
public delegate IPropertySet ConnectionPropertiesDelegate();
public static class TestDelegate
{
public static IPropertySet GetConnection()
{
return new PropertySetClass();
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,AllowMultiple=false,Inherited=true)]
public class WorkspaceAttribute : Attribute
{
public ConnectionPropertiesDelegate ConnectionDelegate { get; set; }
public WorkspaceAttribute(ConnectionPropertiesDelegate connectionDelegate)
{
ConnectionDelegate = connectionDelegate;
}
}
[Workspace(TestDelegate.GetConnection)]
public class Test
{
}
And if its not possible, what are the sensible alternatives?
No, you cannot have a delegate as an attribute constructor parameter. See available types: Attribute parameter types
As a workaround (although it's hacky and error prone) you can create a delegate with reflection:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class WorkspaceAttribute : Attribute
{
public ConnectionPropertiesDelegate ConnectionDelegate { get; set; }
public WorkspaceAttribute(Type delegateType, string delegateName)
{
ConnectionDelegate = (ConnectionPropertiesDelegate)Delegate.CreateDelegate(typeof(ConnectionPropertiesDelegate), delegateType, delegateName);
}
}
[Workspace(typeof(TestDelegate), "GetConnection")]
public class Test
{
}
Other possible workaround is creating abstract base Attribute type with abstract method matching your delegate definition, and then implementing the method in concrete Attribute class.
It has following benefits:
Annotation is more concise and clean (DSL like)
No reflection
Easy to reuse
Example:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple=false, Inherited=true)]
public abstract class GetConnectionAttribute : Attribute
{
public abstract IPropertySet GetConnection();
}
public class GetConnectionFromPropertySetAttribute : GetConnectionAttribute
{
public override IPropertySet GetConnection()
{
return new PropertySetClass();
}
}
[GetConnectionFromPropertySet]
public class Test
{
}
I solved this by using an enum and a mapping array of delegates. Although I really like the idea of using inheritance, in my scenario that would require me to write several child classes to do relatively simple stuff. This should be refactorable as well. The only drawback is that you have to make sure to make the delegate's index in the array corresponds to the enum value.
public delegate string FormatterFunc(string val);
public enum Formatter
{
None,
PhoneNumberFormatter
}
public static readonly FormatterFunc[] FormatterMappings = { null, PhoneNumberFormatter };
public string SomeFunction(string zzz)
{
//The property in the attribute is named CustomFormatter
return FormatterMappings[(int)YourAttributeHere.CustomFormatter](zzz);
}
Necromancing.
Augmented on the accepted answer to use a dynamic delegate type:
namespace NetStandardReporting
{
// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)]
public class DynamicDllImportAttribute
: System.Attribute
{
protected string m_name;
public string Name
{
get
{
return this.m_name;
}
}
public DynamicDllImportAttribute(string name)
: base()
{
this.m_name = name;
}
private static System.Type CreateDelegateType(System.Reflection.MethodInfo methodInfo)
{
System.Func<System.Type[], System.Type> getType;
bool isAction = methodInfo.ReturnType.Equals((typeof(void)));
System.Reflection.ParameterInfo[] pis = methodInfo.GetParameters();
System.Type[] types = new System.Type[pis.Length + (isAction ? 0: 1)];
for (int i = 0; i < pis.Length; ++i)
{
types[i] = pis[i].ParameterType;
}
if (isAction)
{
getType = System.Linq.Expressions.Expression.GetActionType;
}
else
{
getType = System.Linq.Expressions.Expression.GetFuncType;
types[pis.Length] = methodInfo.ReturnType;
}
return getType(types);
}
private static System.Delegate CreateDelegate(System.Reflection.MethodInfo methodInfo, object target)
{
System.Type tDelegate = CreateDelegateType(methodInfo);
if(target != null)
return System.Delegate.CreateDelegate(tDelegate, target, methodInfo.Name);
return System.Delegate.CreateDelegate(tDelegate, methodInfo);
}
// protected delegate string getName_t();
public DynamicDllImportAttribute(System.Type classType, string delegateName)
: base()
{
System.Reflection.MethodInfo mi = classType.GetMethod(delegateName,
System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
);
// getName_t getName = (getName_t)System.Delegate.CreateDelegate(delegateType, mi));
System.Delegate getName = CreateDelegate(mi, null);
object name = getName.DynamicInvoke(null);
this.m_name = System.Convert.ToString(name);
}
} // End Class DynamicDllImportAttribute
public class DynamicDllImportTest
{
private static string GetFreetypeName()
{
if (System.Environment.OSVersion.Platform == System.PlatformID.Unix)
return "libfreetype.so.6";
return "freetype6.dll";
}
// [DynamicDllImportAttribute("freetype6")]
[DynamicDllImportAttribute(typeof(DynamicDllImportTest), "GetFreetypeName")]
public static string bar()
{
return "foobar";
}
// NetStandardReporting.DynamicDllImportTest.Test();
public static void Test()
{
System.Reflection.MethodInfo mi = typeof(DynamicDllImportTest).GetMethod("bar",
System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic);
object[] attrs = mi.GetCustomAttributes(true);
foreach (object attr in attrs)
{
DynamicDllImportAttribute importAttr = attr as DynamicDllImportAttribute;
if (importAttr != null)
{
System.Console.WriteLine(importAttr.Name);
}
} // Next attr
} // End Sub Test
} // End Class
} // End Namespace

Proxying a collection interfaces dynamically

I have occasionally had cause to write collection class adapters, i.e. create an adapter for a class that implements IList<T> proxying its methods, whist adding some extra functionality. The IList interface has numerous methods / properties, I was wondering whether the straight-through proxy methods could be implemented dynamically? I had a look at DynamicObject, but could only find a few simple examples that proxy DTO classes, i.e. proxying a class that just has properties.
Is the proxying of IList<T> possible?
e.g.
public class ListProxy : IList<T>
{
private IList<T> _adaptee;
public ListProxy(IList<T> adaptee)
{
_adaptee = adaptee
}
// dynamically implement straight-through IList methods / properties
}
Something like this?
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
class Program
{
static void Main(string[] args)
{
IList<string> listProxy = MyProxyGenerator.Create<IList<string>>(new ListProxy<string>(new List<string>() { "aa","bb" }));
bool b1 = listProxy.Contains("aa");
bool b2 = listProxy.Contains("cc");
int count = listProxy.Count;
string s = listProxy[1];
}
public class ListProxy<T>
{
private IList<T> _adaptee;
//Only method needed by proxy generator
object Adaptee
{
get { return _adaptee; }
}
public ListProxy(IList<T> adaptee)
{
_adaptee = adaptee;
}
}
class MyProxyGenerator : RealProxy
{
Type _Type;
object _Instance;
public static T Create<T>(object instance)
{
return (T)new MyProxyGenerator(typeof(T),instance).GetTransparentProxy();
}
MyProxyGenerator(Type type,object instance) : base(type)
{
_Type = type;
_Instance = instance.GetType().InvokeMember("get_Adaptee", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, instance, null);
}
public override IMessage Invoke(IMessage msg)
{
IMethodCallMessage methodMessage = new MethodCallMessageWrapper((IMethodCallMessage)msg);
string method = (string)msg.Properties["__MethodName"];
object[] args = (object[])msg.Properties["__Args"];
object retObj = _Instance.GetType().InvokeMember(method, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,null,_Instance,args);
return new ReturnMessage(retObj,methodMessage.Args,methodMessage.ArgCount,methodMessage.LogicalCallContext,methodMessage);
}
}
}

Reflection get type of FieldInfo object?

HI All,
I need to access the class SomeClass which is declared has a private field in the Wrapper class, using Reflection so far i have been able to get private field members . How do i cast it back to its original type so that i could access it properties and other members.
internal class Program
{
private static void Main(string[] args)
{
Wrapper wrap = new Wrapper
{
SOmeProperty = new SomeClass
{
Number = 007
}
};
Type type = wrap.GetType();
FieldInfo[] infos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var item in infos)
{
}
}
}
internal class SomeClass
{
public int Number { get; set; }
}
internal class Wrapper
{
private SomeClass _tempSomeObj;
public SomeClass SOmeProperty
{
get
{
return _tempSomeObj;
}
set
{
_tempSomeObj = value;
}
}
}
I dont know if i understand the question correct. You want the type of the private field (backing field)??
Then you could check the FieldType property of the FieldInfo....
like this:
internal class Program
{
#region Methods
private static void Main(string[] args)
{
var wrap = new Wrapper { SOmeProperty = new SomeClass { Number = 007 } };
Type type = wrap.GetType();
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var fieldInfo in fieldInfos)
{
if (fieldInfo.FieldType == typeof(SomeClass))
{
Console.WriteLine("Yap!");
}
}
}
#endregion
}
internal class SomeClass
{
#region Properties
public int Number { get; set; }
#endregion
}
internal class Wrapper
{
#region Properties
public SomeClass SOmeProperty { get; set; }
#endregion
}
Use PropertyInfo instead:
internal class Program
{
private static void Main(string[] args)
{
Wrapper wrap = new Wrapper
{
SOmeProperty = new SomeClass
{
Number = 007
}
};
Type type = wrap.GetType();
PropertyInfo info = type.GetProperty("SOmeProperty", BindingFlags.NonPublic | BindingFlags.Instance);
SomeClass value = (SomeClass)info.GetValue(wrap, null);
// use `value` variable here
}
}
I'm still a little fuzzy about what your're trying to do, but you can always GetType() on any object and get its actual run time type and query that for properties field of some other type for example
public void ListPropertiesOfType( object targetObject, Type propertyType ) {
foreach( var foundProperty in targetObject.GetType( ).GetProperties( ).Where( p => p.PropertyType == propertyType ) ) {
Console.WriteLine( "Name: {0}, Value: {1}", foundProperty.Name, foundProperty.GetValue( targetObject, null ) );
}
}
ListPropertiesOfType(new Wrapper(), typeof(SomeClass))
ListPropertiesOfType(new Wrapper(), typeof(SomeOtherClass))
If you want to pass in instances of Someclass and SomeClass that is also fine, just use GetType() on the instances to get the type that you can then use to find properties of that type as illustrated above. this works the same way regardless if you make the method generic and pass in "T" or if its non-generic and you pass in "object"

Categories