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;
}
Related
The objective here is to allow API consumers to register their model and how to extract data from that model. Using the ValueMapper below we provide a CreateMap method that registers the map name and function to call to retrieve the data as an object.
The idea here being that certain model have a little more work to get the data out correctly. Once the model is registered using CreateMap we'll store that in an internal list/dictionary for future look ups. I've tried a few different angles to solve this problem and this is very close but still is lacking since the caller cannot provide actual expression logic then can only return a straight value.
I've stripped down the code to the bare bones and if there's a better way to solve my problem i'm open to suggestions.
// static class that I would like to hold a list of 'expressions' that can be looked up and executed multuples times by the run time logic
public static class ValueMapper
{
private static Dictionary<string, LambdaExpression> _rules = new Dictionary<string, LambdaExpression>();
public static void CreateMap<T>(string ruleName, Expression<Func<T, object>> valueExpression)
{
_rules.Add(ruleName, valueExpression);
}
}
public class Consumer
{
public Consumer()
{
// This works but doesn't allow for registering further logic
ValueMapper.CreateMap<ExternalUser>("foo", user => user.FirstName);
// This has a compiler error as follows : "A lambda expression with a statement body cannot be converted to an expression tree"
ValueMapper.CreateMap<ExternalUser>("foo", user =>
{
return user.FirstName + user.LastName;
});
}
}
// some external class
public class ExternalUser
{
public string FirstName
{
get;
set;
}
public string LastName
{
get;
set;
}
}
From your description it seems you don't need expressions, simple delegates should do:
public static class ValueMapper {
private static Dictionary<string, Func<object, object>> _rules = new Dictionary<string, Func<object, object>>();
public static void CreateMap<T>(string ruleName, Func<T, object> valueFunc) {
_rules.Add(ruleName, c => valueFunc((T) c));
}
}
If there is only one mapping per target type - no need to use strings, use types:
public static class ValueMapper {
private static Dictionary<Type, Func<object, object>> _rules = new Dictionary<Type, Func<object, object>>();
public static void CreateMap<TFrom, TTo>(Func<TFrom, TTo> valueFunc) {
_rules.Add(typeof(TFrom), c => valueFunc((TFrom)c));
}
public static object Map<T>(T instance) {
if (_rules.ContainsKey(typeof(T)))
return _rules[typeof(T)](instance);
// or throw here, or return null, depending on what you need
return instance;
}
}
If you know types you are mapping to - use them:
public static class ValueMapper {
private static Dictionary<Type, Func<object, object>> _rules = new Dictionary<Type, Func<object, object>>();
public static void CreateMap<TFrom, TTo>(Func<TFrom, TTo> valueFunc) {
_rules.Add(typeof(TFrom), c => valueFunc((TFrom)c));
}
public static TTo Map<TTo>(object instance) {
if (_rules.ContainsKey(instance.GetType()))
return (TTo) _rules[instance.GetType()](instance);
// throw here if necessary
return default(TTo);
}
}
I have created an architecture in my C# code which does exactly what I want, but seems it would be very difficult to maintain in the long-run and am hoping there's a design pattern / better architecture I could be pointed towards.
I have created an object Test which, again, does exactly what I need perfectly which has the following structure:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
private Lazy<object> _test1;
public object Test1 { get { return _test1.Value; } }
private Lazy<object> _test2;
public object Test2 { get { return _test2.Value; } }
public Test()
{
_test1 = new Lazy<object>(() => MethodDictionary["Test1"](this), true);
_test2 = new Lazy<object>(() => MethodDictionary["Test2"](this), true);
}
}
What this allows me to do is, at run-time to assign a dictionary of functions to my Test object and the 2 properties Test1 & Test2 will use the functions loaded into it to return values.
The implementation looking somewhat as follows:
class Program
{
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1.ToString());
Console.WriteLine(x.Test2.ToString());
Console.ReadKey();
}
private static object TestMethod1(Test t)
{ return t.Var1 + t.Var2; }
private static object TestMethod2(Test t)
{ return t.Var1 - t.Var2; }
}
And it works great and has proven very efficient for large sets of Test objects.
My challenge is that if I ever want to add in a new method to my Test class, I need to add in the:
private Lazy<object> _myNewMethod;
public object MyNewMethod { get { return _myNewMethod.Value; } }
Update the constuctor with the key to look for in the dictionary
And, although that is pretty simple, I'd love to have a 1-line add-in (maybe some form of custom object) or have the properties read directly form the dictionary without any need for defining them at all.
Any ideas? ANY help would be great!!!
Thanks!!!
One of the ways in which you could achieve your desired behavior, is to use something that resembles a miniature IoC framework for field injection, tuned to your specific use case.
To make things easier, allow less typing in your concrete classes and make things type-safe, we introduce the LazyField type:
public class LazyField<T>
{
private static readonly Lazy<T> Default = new Lazy<T>();
private readonly Lazy<T> _lazy;
public LazyField() : this(Default) { }
public LazyField(Lazy<T> lazy)
{
_lazy = lazy;
}
public override string ToString()
{
return _lazy.Value.ToString();
}
public static implicit operator T(LazyField<T> instance)
{
return instance._lazy.Value;
}
}
Furthermore, we define an abstract base class, that ensures that these fields will be created at construction time:
public abstract class AbstractLazyFieldHolder
{
protected AbstractLazyFieldHolder()
{
LazyFields.BuildUp(this); // ensures fields are populated.
}
}
Skipping for a moment how this is achieved (explained further below), this allows the following way of defining your Test class:
public class Test : AbstractLazyFieldHolder
{
public double Var1;
public double Var2;
public readonly LazyField<double> Test1;
public readonly LazyField<double> Test2;
}
Note that these fields are immutable, initialized in the constructor. Now, for your usage example, the below snippet shows the "new way" of doing this:
LazyFields.Configure<Test>()
// We can use a type-safe lambda
.SetProvider(x => x.Test1, inst => inst.Var1 + inst.Var2)
// Or the field name.
.SetProvider("Test2", TestMethod2);
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1);
double test2Val = x.Test2; // type-safe conversion
Console.WriteLine(test2Val);
// Output:
// 50
// -10
The class below provides the services that support the configuration and injection of these field value.
public static class LazyFields
{
private static readonly ConcurrentDictionary<Type, IBuildUp> _registry = new ConcurrentDictionary<Type,IBuildUp>();
public interface IConfigureType<T> where T : class
{
IConfigureType<T> SetProvider<FT>(string fieldName, Func<T, FT> provider);
IConfigureType<T> SetProvider<F, FT>(Expression<Func<T, F>> fieldExpression, Func<T, FT> provider) where F : LazyField<FT>;
}
public static void BuildUp(object instance)
{
System.Diagnostics.Debug.Assert(instance != null);
var builder = _registry.GetOrAdd(instance.GetType(), BuildInitializer);
builder.BuildUp(instance);
}
public static IConfigureType<T> Configure<T>() where T : class
{
return (IConfigureType<T>)_registry.GetOrAdd(typeof(T), BuildInitializer);
}
private interface IBuildUp
{
void BuildUp(object instance);
}
private class TypeCfg<T> : IBuildUp, IConfigureType<T> where T : class
{
private readonly List<FieldInfo> _fields;
private readonly Dictionary<string, Action<T>> _initializers;
public TypeCfg()
{
_fields = typeof(T)
.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Where(IsLazyField)
.ToList();
_initializers = _fields.ToDictionary(x => x.Name, BuildDefaultSetter);
}
public IConfigureType<T> SetProvider<FT>(string fieldName, Func<T,FT> provider)
{
var pi = _fields.First(x => x.Name == fieldName);
_initializers[fieldName] = BuildSetter<FT>(pi, provider);
return this;
}
public IConfigureType<T> SetProvider<F,FT>(Expression<Func<T,F>> fieldExpression, Func<T,FT> provider)
where F : LazyField<FT>
{
return SetProvider((fieldExpression.Body as MemberExpression).Member.Name, provider);
}
public void BuildUp(object instance)
{
var typedInstance = (T)instance;
foreach (var initializer in _initializers.Values)
initializer(typedInstance);
}
private bool IsLazyField(FieldInfo fi)
{
return fi.FieldType.IsGenericType && fi.FieldType.GetGenericTypeDefinition() == typeof(LazyField<>);
}
private Action<T> BuildDefaultSetter(FieldInfo fi)
{
var itemType = fi.FieldType.GetGenericArguments()[0];
var defValue = Activator.CreateInstance(typeof(LazyField<>).MakeGenericType(itemType));
return (inst) => fi.SetValue(inst, defValue);
}
private Action<T> BuildSetter<FT>(FieldInfo fi, Func<T, FT> provider)
{
return (inst) => fi.SetValue(inst, new LazyField<FT>(new Lazy<FT>(() => provider(inst))));
}
}
private static IBuildUp BuildInitializer(Type targetType)
{
return (IBuildUp)Activator.CreateInstance(typeof(TypeCfg<>).MakeGenericType(targetType));
}
}
Look at library https://github.com/ekonbenefits/impromptu-interface.
With it and using DynamicObject i wrote sample code that shows how to simplify adding new methods:
public class Methods
{
public Methods()
{
MethodDictionary = new Dictionary<string, Func<ITest, object>>();
LazyObjects = new Dictionary<string, Lazy<object>>();
}
public Dictionary<string, Func<ITest, object>> MethodDictionary { get; private set; }
public Dictionary<string, Lazy<object>> LazyObjects { get; private set; }
}
public class Proxy : DynamicObject
{
Methods _methods;
public Proxy()
{
_methods = new Methods();
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _methods.LazyObjects[binder.Name].Value;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_methods.MethodDictionary[binder.Name] = (Func<ITest, object>)value;
_methods.LazyObjects[binder.Name] = new Lazy<object>(() => _methods.MethodDictionary[binder.Name](this.ActLike<ITest>()), true);
return true;
}
}
//now you can add new methods by add single method to interface
public interface ITest
{
object Test1 { get; set; }
object Test2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var x = new Proxy().ActLike<ITest>();
x.Test1 = new Func<ITest, object>((y) => "Test1");
x.Test2 = new Func<ITest, object>((y) => "Test2");
Console.WriteLine(x.Test1);
Console.WriteLine(x.Test2);
}
}
I don't know what you are trying to do, but I think you can use a simpler approach like this:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
}
Calling the function is simple:
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(Test.MethodDictionary["Test1"](x).ToString());
Console.WriteLine(Test.MethodDictionary["Test2"](x).ToString());
Console.ReadKey();
}
I have a series of static classes that I use to get strings for enum values. They all look something like this:
public static class MyEnumToString
{
private static Dictionary<MyEnum, string> map
= new Dictionary<MyEnum, string>();
public static string Get(MyEnum type)
{
PopulateEmptyMap();
return map[type];
}
static void PopulateEmptyMap()
{
if (!map.Any())
{
PopulateMap();
}
}
private static void PopulateMap()
{
map[MyEnum.enum1] = "string for enum 1";
map[MyEnum.enum2] = "string for enum 2";
}
}
I have multiple classes like this, that differ in the Enum type they use, and the string values. Clearly, I should combine the classes to reduce duplicated code.
What I tried doing was create generic base class so that it can handle any type, then implement the PopulateMap for the inherited classes. If it were possible, it would look something like this:
public static class TypeToString<TType>
{
public static Dictionary<TType, string> map
= new Dictionary<TType, string>();
public static string Get(TType type)
{
PopulateEmptyMap();
return map[type];
}
static void PopulateEmptyMap()
{
if (!map.Any())
{
PopulateMap();
}
}
public abstract static void PopulateMap();
}
public static class MyEnumToString: TypeToString<MyEnum>
{
public static void PopulateMap()
{
map[MyEnum.enum1] = "string for enum 1";
map[MyEnum.enum2] = "string for enum 2";
}
}
I had to make the Dictionary and the method PopulateMap public, because apparently generic classes cannot have protected or protected-internal members. Having to make that public isn't ideal, but not a deal-breaker.
What I am getting hung up on is the fact that "overridable methods cannot be static", so my PopulateMap method cannot be both abstract and static. And if it's not static, it can't be called from other static methods. And if it's not abstract, then the inheriting classes' PopulateMap doesn't get called.
This version doesn't even build.
Is there any way to do what I'm trying to do and still keep my class static? I'd really like to avoid having to have an instantiated TypeToString object every time I want to call TypeToString.Get().
Here's a handy extension method, as I'm guessing you're trying to map some description text to an enum value:
public static class EnumExtensions
{
public static string GetDescription(this Enum value)
{
var field = value.GetType().GetField(value.ToString());
if (field == null)
return value.ToString();
var attribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false)
.OfType<DescriptionAttribute>()
.SingleOrDefault();
return attribute != null
? attribute.Description
: value.ToString();
}
}
Use it like this:
public enum Foo
{
[Description("Hello")]
Bar,
[Description("World")]
Baz
}
var value = Foo.Bar;
var description = value.GetDescription(); // Hello
Depending on your needs, you could cache the descriptions if reflection proves to be too slow for you, just modify the GetDescription method.
EDIT: to account for the additional info in the comment.
As it looks like you need something more extensible, you could use a custom attribute:
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
public sealed class DescriptionEntryAttribute : Attribute
{
public string Key { get; private set; }
public string Value { get; private set; }
public DescriptionEntryAttribute(string key, string value)
{
Key = key;
Value = value;
}
}
Which would let you to do this:
public enum Foo
{
[DescriptionEntry("Name", "Hello")]
[DescriptionEntry("Title", "Some title")]
Bar,
[DescriptionEntry("Name", "World")]
[DescriptionEntry("Title", "Some title")]
Baz
}
Now, to read this thing, I'd advise you to store it in a cache like that:
public static class EnumExtensions
{
private static readonly ConcurrentDictionary<Type, DescriptionCache> Caches = new ConcurrentDictionary<Type, DescriptionCache>();
public static string GetDescription(this Enum value, string key)
{
var enumType = value.GetType();
var cache = Caches.GetOrAdd(enumType, type => new DescriptionCache(type));
return cache.GetDescription(value, key);
}
public static IEnumerable<TEnum> GetValuesFromDescription<TEnum>(string key, string description)
where TEnum : struct
{
var cache = Caches.GetOrAdd(typeof(TEnum), type => new DescriptionCache(type));
return cache.GetValues(key, description).Select(value => (TEnum)(object)value);
}
private class DescriptionCache
{
private readonly ILookup<Enum, Tuple<string, string>> _items;
private readonly ILookup<Tuple<string, string>, Enum> _reverse;
public DescriptionCache(Type enumType)
{
if (!enumType.IsEnum)
throw new ArgumentException("Not an enum");
_items = (from value in Enum.GetValues(enumType).Cast<Enum>()
let field = enumType.GetField(value.ToString())
where field != null
from attribute in field.GetCustomAttributes(typeof (DescriptionEntryAttribute), false).OfType<DescriptionEntryAttribute>()
select new {value, key = attribute.Key, description = attribute.Value})
.ToLookup(i => i.value, i => Tuple.Create(i.key, i.description));
_reverse = (from grp in _items
from description in grp
select new {value = grp.Key, description})
.ToLookup(i => i.description, i => i.value);
}
public string GetDescription(Enum value, string key)
{
var tuple = _items[value].FirstOrDefault(i => i.Item1 == key);
return tuple != null ? tuple.Item2 : null;
}
public IEnumerable<Enum> GetValues(string key, string description)
{
return _reverse[Tuple.Create(key, description)];
}
}
}
This way:
Foo.Bar.GetDescription("Name") returns "Hello"
EnumExtensions.GetValuesFromDescription<Foo>("Title", "Some title") returns a sequence containing Foo.Bar and Foo.Baz
That should be enough to get you started, now you should tweak it to your needs. For instance, you could use an enum instead of a string for the keys, it would help avoid typing mistakes, but I don't know if this would suit your needs.
Your problem is that static methods and variables are essentially not inherited. They are variables that don't act on instances of the class themselves, but provide some functionality to the class.
So you have a bunch of different enums, and you want to populate them based on different stuff. So let's look at what parts you have, and what is common:
PopulateMap: Not common
Enum type: Not common
Storage variable: Common
Populate Map if empty: Common
So all you really want is a way to populate the map once, when it's used. There is already a class for this, it's called Lazy. Using that, the code becomes:
public abstract class TypeToString<Type>
{
protected TypeToString()
{
storage = new Lazy<Dictionary<Type, string>>(GetMap);
}
private Lazy<Dictionary<Type, string>> storage;
protected abstract Dictionary<Type, string> GetMap();
public string Get(Type t) {return storage.Value[t];}
}
public class MyEnumToString : TypeToString<MyEnum>
{
protected override Dictionary<MyEnum, string> GetMap()
{
return null;
}
public static Get(MyEnum e) { return new MyEnumToString.Get(e); }
}
Alternatively, you can decorate your enums with a [DescriptionAttribute] and then create a method to get the description of a specific enum. This is what I did when I was faced with a similar problem. (Be sure to cache the results for the enum, as it used reflection which was slow.)
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;
}
}
I wrote a class that allows a derivate to specify which of its properties can be lazy loaded. The code is:
public abstract class SelfHydratingEntity<T> : DynamicObject where T : class {
private readonly Dictionary<string, LoadableBackingField> fields;
public SelfHydratingEntity(T original) {
this.Original = original;
this.fields = this.GetBackingFields().ToDictionary(f => f.Name);
}
public T Original { get; private set; }
protected virtual IEnumerable<LoadableBackingField> GetBackingFields() {
yield break;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
result = field.GetValue();
return true;
} else {
var getter = PropertyAccessor.GetGetter(this.Original.GetType(), binder.Name);
result = getter(this.Original);
return true;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
field.SetValue(value);
return true;
} else {
var setter = PropertyAccessor.GetSetter(this.Original.GetType(), binder.Name);
setter(this.Original, value);
return true;
}
}
}
And a derivate class:
public class SelfHydratingPerson : SelfHydratingEntity<IPerson> {
private readonly IDataRepository dataRepository;
public SelfHydratingDerivate(IDataRepository dataRepository, IPerson person)
: base(person) {
this.dataRepository = dataRepository
}
protected override IEnumerable<LoadableBackingField> GetBackingFields() {
yield return new LoadableBackingField("Address", () => this.dataRepository.Addresses.Get(this.Original.AddressID));
}
}
This works perfectly fine for getting and settings property values, but I get a either a RuntimeBinderException when I implicitly cast or an InvalidCastException with an explicitly cast SelfHydratingEntity back to T.
I know that you can override the DynamicObject.TryConvert method, but I'm wondering what exactly to put in this method. I've read a lot about duck typing today, and have tried out several libraries, but none of them work for this particular scenario. All of the libraries I've tried today generate a wrapper class using Reflection.Emit that makes calls to "get_" and "set_" methods and naturally use reflection to find these methods on the wrapped instance. SelfHydratingEntity of course doesn't have the "get_" and "set_" methods defined.
So, I'm wondering if this kind of thing is even possible. Is there any way to cast an instance of SelfHydratingEntity to T? I'm looking for something like this:
var original = GetOriginalPerson();
dynamic person = new SelfHydratingPerson(new DataRepository(), original);
string name = person.Name; // Gets property value on original
var address = person.Address; // Gets property value using LoadableBackingField registration
var iPerson = (IPerson)person;
- or -
var iPerson = DuckType.As<IPerson>(person);
Have you seen this Duck Typing project. It looks pretty good. I have just found a great example from Mauricio. It uses the Windsor Castle dynamic proxy to intercept method calls
Using the code from Mauricio the following code works like a dream
class Program
{
static void Main(string[] args)
{
dynamic person = new { Name = "Peter" };
var p = DuckType.As<IPerson>(person);
Console.WriteLine(p.Name);
}
}
public interface IPerson
{
string Name { get; set; }
}
public static class DuckType
{
private static readonly ProxyGenerator generator = new ProxyGenerator();
public static T As<T>(object o)
{
return generator.CreateInterfaceProxyWithoutTarget<T>(new DuckTypingInterceptor(o));
}
}
public class DuckTypingInterceptor : IInterceptor
{
private readonly object target;
public DuckTypingInterceptor(object target)
{
this.target = target;
}
public void Intercept(IInvocation invocation)
{
var methods = target.GetType().GetMethods()
.Where(m => m.Name == invocation.Method.Name)
.Where(m => m.GetParameters().Length == invocation.Arguments.Length)
.ToList();
if (methods.Count > 1)
throw new ApplicationException(string.Format("Ambiguous method match for '{0}'", invocation.Method.Name));
if (methods.Count == 0)
throw new ApplicationException(string.Format("No method '{0}' found", invocation.Method.Name));
var method = methods[0];
if (invocation.GenericArguments != null && invocation.GenericArguments.Length > 0)
method = method.MakeGenericMethod(invocation.GenericArguments);
invocation.ReturnValue = method.Invoke(target, invocation.Arguments);
}
}
impromptu-interface
https://github.com/ekonbenefits/impromptu-interface
Can static cast interfaces onto objects derived from DynamicObject.