Duck Typing DynamicObject derivate - c#

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.

Related

How to serialize/deserialze a class that implements IEnumerator, IEnumerable?

Just want to stress out this question is irrelevant of why this technology and why not that. This is related to C# code.
I searched below but none provides solution.
Serialize a class that implements IEnumerable
Serialization on classes that implement IEnumerator
I am working on WCF Rest project in C# which is replacing .NET Remoting communication layer. I use Newtonsoft dll to serialize and de-serialize.
I have a class called MyDTO which implements IEnumerator, IEnumerable which I cannot change since this is old class and many applications in production use them. When I try to serialize MyDTO into string I do not get any error/exception message, I just get an empty array like "[]". Can anybody tell how we can serialize/deserialze class that implements IEnumerator, IEnumerable?
public class MyDTO : IEnumerator, IEnumerable
I am calling a method called ABC in OldServer.dll which gives me MyDTO object. I want to convert this to string and again from string to MyDTO.
Please let me know if you need more information. Please see below for MyDTO class which I cannot change:
[Serializable]
public class MyDTO : IEnumerator, IEnumerable
{
#region Inner Types
internal class MyObjComparer : IComparer<MyObj>
{
public int Compare(MyObj x, MyObj y)
{
return x.InputCode.CompareTo(y.InputCode);
}
}
#endregion
#region Variables
private List<MyObj> myObjList;
private string selectedObjectMessage;
private bool containSequenceNo = false;
private bool sortEnabled;
private bool filterEnabled;
private IComparer<MyObj> objectComparer;
#endregion
#region Constructors
public MyDTO()
{
this.myObjList = new List<MyObj>();
this.selectedObjectMessage = string.Empty;
}
public MyDTO(List<MyObj> objects)
{
this.myObjList = objects;
this.selectedObjectMessage = string.Empty;
}
public MyDTO(IComparer<MyObj> argSortComparer)
: this()
{
this.objectComparer = argSortComparer;
}
public MyDTO(List<MyObj> argErrors, IComparer<MyObj> argSortComparer)
: this(argErrors)
{
this.objectComparer = argSortComparer;
}
public MyDTO(List<MyObj> argErrors, IComparer<MyObj> argSortComparer, bool argSortEnabled)
: this(argErrors, argSortComparer)
{
this.sortEnabled = argSortEnabled;
}
#endregion
#region Properties
public string selectedObjectMessage
{
get { return this.selectedObjectMessage; }
set
{
if (value == null)
value = string.Empty;
this.selectedObjectMessage = value;
}
}
public int Count
{
get { return this.myObjList.Count; }
}
public bool ErrorsContainsSequenceNo
{
get { return this.containSequenceNo; }
set { this.containSequenceNo = value; }
}
public List<MyObj> myObjList
{
get { return this.myObjList; }
set { this.myObjList = value; }
}
public MyDTO WithoutEmptyMyObjects
{
get
{
MyDTO objs = new MyDTO();
foreach (MyObj obj in this.myObjList)
{
if (!string.IsNullOrEmpty(obj.InputCode))
objs.Add(obj);
}
return objs;
}
}
#endregion
}
UPDATE 1:
After spending almost a day we decided to write our own method targeting MyDTO which will produce XmlDocument which is serialize. Using that same XmlDocument we will try create MyDTO object. I feel we need to just concentrate on properties that has setters. I will let you know.
Using the almighty Json.Net
1) Create a contract resolver to serialize/deserialize specific members based on their accessibility, cause by default serialization/deserialization only happens for public members.
public class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.ToList();
props.ForEach(p => { p.Writable = true; p.Readable = true; });
return props;
}
}
2) Then you can serialize your object like
var settings = new JsonSerializerSettings() { ContractResolver = new MyContractResolver() };
// dtoInstance is your dto instance you wish to serialize.
string serializedDTO = JsonConvert.SerializeObject(dtoInstance, settings);
3) And you can deserialize like
var settings = new JsonSerializerSettings() { ContractResolver = new MyContractResolver() };
MyDTO deserializedDTO = JsonConvert.DeserializeObject<MyDTO>(serializedDTO, settings);

Factory class using generics but without base class

Ive got what I think may be an unusual problem (Ive searched around a lot for an answer, but I dont think Ive found one).
I have messages that are read from a queue and depending on the message type contains a payload that needs to be deserialized into a concrete c# class. This needs to eventually be concrete (I cant use generics the whole way) because Im using Expression Trees to perform Evaluations on the classes that arrive from the queue.
The base class looks like this:
public abstract class BaseRuleMessage<T>
{
public abstract Func<T, bool> CompileRule(Rule r, T msg);
public T Deserialize(ClientEventQueueMessage message)
{
return JsonConvert.DeserializeObject<T>(message.Payload);
}
public BaseRuleMessage()
{
RulesCompleted = new List<int>();
}
public IEnumerable<Rule> FilterRules(RuleGroup ruleGroup)
{
return ruleGroup.Rules.Where(item =>
!RulesCompleted.Any(r => r.Equals(item.Id)));
}
I implement the base class like this:
public class UiTransactionUpdate : BaseRuleMessage<UiTransactionUpdate>
{
public override Func<UiTransactionUpdate, bool> CompileRule(Rule r, UiTransactionUpdate msg)
{
var expression = Expression.Parameter(typeof(UiTransactionUpdate));
Expression expr = BuildExpr(r, expression, msg);
return Expression.Lambda<Func<UiTransactionUpdate, bool>>(expr, expression).Compile();
}
public Guid TransactionId { get; set; }
public Guid GroupId { get; set; }
public decimal StatusValue { get; set; }
I then do something like this to call:
switch (message.MessageType)
{
case "UI_UPDATE":
{
message.Payload = RemoveNullGroupIdReference(jsonPayload, message.Payload);
var deserializedMessage = new UiTransactionUpdate().Deserialize(message);
deserializedMessage.RulesCompleted = deserializedMessage.RulesCompleted ?? new List<int>();
foreach (var rule in deserializedMessage.FilterRules(ruleGroup))
{
What I really want to know is how can I create a factory (or can I?) to be able to define the implementation of the base class in such a way that I can return a concrete class to use for my expression tree evaluations without having to repeat all the calling code for each type.
I avoided using dynamic but this meant that I had pass the object around as an object. I prefer not to use dynamic but in this case, casting objects at run-time may not be any better.
I also had to change the code so that instead of returning a Func<T, bool>, there is a method that would execute the Func. This was to avoid referring to the generic class. I'm not sure if you actually need the Func in your actual implementation.
I had to create a new base class that wasn't generically typed.
// Horrible name, do change it to something more appropriate
public abstract class BaseBaseRuleMessage
{
public IList<int> RulesCompleted { get; set; }
public IEnumerable<Rule> FilterRules(RuleGroup ruleGroup)
{
return ruleGroup.Rules.Where(item =>
!RulesCompleted.Any(r => r.Equals(item.Id)));
}
public BaseBaseRuleMessage DeserializeToBaseBaseRuleMessage(ClientEventQueueMessage message)
{
return (BaseBaseRuleMessage) DeserializeToType(message);
}
protected abstract object DeserializeToType(ClientEventQueueMessage message);
public abstract bool ExecuteRule(Rule rule, object msg);
}
Updated the BaseRuleMessage to derive from BaseBaseRuleMessage (and moved some properties to the base class.
public abstract class BaseRuleMessage<T> : BaseBaseRuleMessage
where T : BaseRuleMessage<T>
{
public abstract Func<T, bool> CompileRule(Rule r, T msg);
protected override object DeserializeToType(ClientEventQueueMessage message)
{
return JsonConvert.DeserializeObject(message.Payload, typeof(T));
}
protected BaseRuleMessage()
{
RulesCompleted = new List<int>();
}
public override bool ExecuteRule(Rule rule, object msg)
{
var message = (T) msg;
if (message == null)
{
throw new InvalidOperationException();
}
return CompileRule(rule, message).Invoke(message);
}
}
The concrete class is basically the same. I've implemented my own BuildExpr to make sure the code can compile.
public class UiTransactionUpdate : BaseRuleMessage<UiTransactionUpdate>
{
public override Func<UiTransactionUpdate, bool> CompileRule(Rule r, UiTransactionUpdate msg)
{
var expression = Expression.Parameter(typeof(UiTransactionUpdate));
Expression expr = BuildExpr(r, expression, msg);
return Expression.Lambda<Func<UiTransactionUpdate, bool>>(expr, expression).Compile();
}
public Guid TransactionId { get; set; }
public Guid GroupId { get; set; }
public decimal StatusValue { get; set; }
private Expression BuildExpr(Rule rule, ParameterExpression parameterExpression, UiTransactionUpdate message)
{
var transactionIdProperty = Expression.Property(parameterExpression, "TransactionId");
var value = Expression.Constant(rule.TransactionId);
return Expression.Equal(transactionIdProperty, value);
}
}
To use it:
var messageTypeToTypeMap = new Dictionary<string, Func<BaseBaseRuleMessage>>
{
{"UI_UPDATE", () => new UiTransactionUpdate()}
};
var factoryFunc = messageTypeToTypeMap[message.MessageType];
message.Payload = RemoveNullGroupIdReference(jsonPayload, message.Payload);
var ruleMessage = factoryFunc.Invoke();
var deserializedMessage = ruleMessage.DeserializeToBaseBaseRuleMessage(message);
deserializedMessage.RulesCompleted = deserializedMessage.RulesCompleted ?? new List<int>();
foreach (var rule in deserializedMessage.FilterRules(ruleGroup))
{
var isTrue = deserializedMessage.ExecuteRule(rule, deserializedMessage);
}

Assigning methods to object at run-time - Design Pattern

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();
}

Instantiating Immutable Objects With Reflection

I created a base class to help me reduce boilerplate code of the initialization of the immutable Objects in C#,
I'm using lazy initialization in order to try not to impact performance a lot ,
I was wondering how much am I affecting the performance by doing this?
This is my base class:
public class ImmutableObject<T>
{
private readonly Func<IEnumerable<KeyValuePair<string, object>>> initContainer;
protected ImmutableObject() {}
protected ImmutableObject(IEnumerable<KeyValuePair<string,object>> properties)
{
var fields = GetType().GetFields().Where(f=> f.IsPublic);
var fieldsAndValues =
from fieldInfo in fields
join keyValuePair in properties on fieldInfo.Name.ToLower() equals keyValuePair.Key.ToLower()
select new {fieldInfo, keyValuePair.Value};
fieldsAndValues.ToList().ForEach(fv=> fv.fieldInfo.SetValue(this,fv.Value));
}
protected ImmutableObject(Func<IEnumerable<KeyValuePair<string,object>>> init)
{
initContainer = init;
}
protected T setProperty(string propertyName, object propertyValue, bool lazy = true)
{
Func<IEnumerable<KeyValuePair<string, object>>> mergeFunc = delegate
{
var propertyDict = initContainer == null ? ObjectToDictonary () : initContainer();
return propertyDict.Select(p => p.Key == propertyName? new KeyValuePair<string, object>(propertyName, propertyValue) : p).ToList();
};
var containerConstructor = typeof(T).GetConstructors()
.First( ce => ce.GetParameters().Count() == 1 && ce.GetParameters()[0].ParameterType.Name == "Func`1");
return (T) (lazy ? containerConstructor.Invoke(new[] {mergeFunc}) : DictonaryToObject<T>(mergeFunc()));
}
private IEnumerable<KeyValuePair<string,object>> ObjectToDictonary()
{
var fields = GetType().GetFields().Where(f=> f.IsPublic);
return fields.Select(f=> new KeyValuePair<string,object>(f.Name, f.GetValue(this))).ToList();
}
private static object DictonaryToObject<T>(IEnumerable<KeyValuePair<string,object>> objectProperties)
{
var mainConstructor = typeof (T).GetConstructors()
.First(c => c.GetParameters().Count()== 1 && c.GetParameters().Any(p => p.ParameterType.Name == "IEnumerable`1") );
return mainConstructor.Invoke(new[]{objectProperties});
}
public T ToObject()
{
var properties = initContainer == null ? ObjectToDictonary() : initContainer();
return (T) DictonaryToObject<T>(properties);
}
}
Can be implemented like so:
public class State:ImmutableObject<State>
{
public State(){}
public State(IEnumerable<KeyValuePair<string,object>> properties):base(properties) {}
public State(Func<IEnumerable<KeyValuePair<string, object>>> func):base(func) {}
public readonly int SomeInt;
public State someInt(int someInt)
{
return setProperty("SomeInt", someInt);
}
public readonly string SomeString;
public State someString(string someString)
{
return setProperty("SomeString", someString);
}
}
and can be used like this:
//creating new empty object
var state = new State();
// Set fields, will return an empty object with the "chained methods".
var s2 = state.someInt(3).someString("a string");
// Resolves all the "chained methods" and initialize the object setting all the fields by reflection.
var s3 = s2.ToObject();
As was already mentioned in the comments, it would make more sense, not to "conflate" the immutable instance implementation or interface with the behavior of what is essentially a builder for new instances.
You could make a much cleaner and quite type safe solution that way. So we could define some marker interfaces and type safe versions thereof:
public interface IImmutable : ICloneable { }
public interface IImmutableBuilder { }
public interface IImmutableOf<T> : IImmutable where T : class, IImmutable
{
IImmutableBuilderFor<T> Mutate();
}
public interface IImmutableBuilderFor<T> : IImmutableBuilder where T : class, IImmutable
{
T Source { get; }
IImmutableBuilderFor<T> Set<TFieldType>(string fieldName, TFieldType value);
IImmutableBuilderFor<T> Set<TFieldType>(string fieldName, Func<T, TFieldType> valueProvider);
IImmutableBuilderFor<T> Set<TFieldType>(Expression<Func<T, TFieldType>> fieldExpression, TFieldType value);
IImmutableBuilderFor<T> Set<TFieldType>(Expression<Func<T, TFieldType>> fieldExpression, Func<TFieldType, TFieldType> valueProvider);
T Build();
}
And provide all the required basic builder behavior in a class like below. Note that most error checking/compiled delegate creation is omitted for the sake of brevity/simplicity. A cleaner, performance optimized version with a reasonable level of error checking can be found in this gist.
public class DefaultBuilderFor<T> : IImmutableBuilderFor<T> where T : class, IImmutableOf<T>
{
private static readonly IDictionary<string, Tuple<Type, Action<T, object>>> _setters;
private List<Action<T>> _mutations = new List<Action<T>>();
static DefaultBuilderFor()
{
_setters = GetFieldSetters();
}
public DefaultBuilderFor(T instance)
{
Source = instance;
}
public T Source { get; private set; }
public IImmutableBuilderFor<T> Set<TFieldType>(string fieldName, TFieldType value)
{
// Notes: error checking omitted & add what to do if `TFieldType` is not "correct".
_mutations.Add(inst => _setters[fieldName].Item2(inst, value));
return this;
}
public IImmutableBuilderFor<T> Set<TFieldType>(string fieldName, Func<T, TFieldType> valueProvider)
{
// Notes: error checking omitted & add what to do if `TFieldType` is not "correct".
_mutations.Add(inst => _setters[fieldName].Item2(inst, valueProvider(inst)));
return this;
}
public IImmutableBuilderFor<T> Set<TFieldType>(Expression<Func<T, TFieldType>> fieldExpression, TFieldType value)
{
// Error checking omitted.
var memberExpression = fieldExpression.Body as MemberExpression;
return Set<TFieldType>(memberExpression.Member.Name, value);
}
public IImmutableBuilderFor<T> Set<TFieldType>(Expression<Func<T, TFieldType>> fieldExpression, Func<TFieldType, TFieldType> valueProvider)
{
// Error checking omitted.
var memberExpression = fieldExpression.Body as MemberExpression;
var getter = fieldExpression.Compile();
return Set<TFieldType>(memberExpression.Member.Name, inst => valueProvider(getter(inst)));
}
public T Build()
{
var result = (T)Source.Clone();
_mutations.ForEach(x => x(result));
return result;
}
private static IDictionary<string, Tuple<Type, Action<T, object>>> GetFieldSetters()
{
// Note: can be optimized using delegate setter creation (IL).
return typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(x => !x.IsLiteral)
.ToDictionary(
x => x.Name,
x => SetterEntry(x.FieldType, (inst, val) => x.SetValue(inst, val)));
}
private static Tuple<Type, Action<T, object>> SetterEntry(Type type, Action<T, object> setter)
{
return Tuple.Create(type, setter);
}
}
Example usage
This could then be used like this, using your example class of State:
public static class Example
{
public class State : IImmutableOf<State>
{
public State(int someInt, string someString)
{
SomeInt = someInt;
SomeString = someString;
}
public readonly int SomeInt;
public readonly string SomeString;
public IImmutableBuilderFor<State> Mutate()
{
return new DefaultBuilderFor<State>(this);
}
public object Clone()
{
return base.MemberwiseClone();
}
public override string ToString()
{
return string.Format("{0}, {1}", SomeInt, SomeString);
}
}
public static void Run()
{
var original = new State(10, "initial");
var mutatedInstance = original.Mutate()
.Set("SomeInt", 45)
.Set(x => x.SomeString, "Hello SO")
.Build();
Console.WriteLine(mutatedInstance);
mutatedInstance = original.Mutate()
.Set(x => x.SomeInt, val => val + 10)
.Build();
Console.WriteLine(mutatedInstance);
}
}
With the following output:
45, Hello SO
20, initial
Well to answer your question about performance, reflection is very expensive (relatively speaking). I would not use your design if it's in performance critical code.
When it comes to generics and reflection the performance hit can often be surprisingly large. Consider even something as simple as this:
public class Builder<T> where T : new()
{
public T Build()
{
return new T();
}
}
What this is actually doing is calling Activator.CreateInstance which uses reflection and it's extremely expensive.
If I wanted to optimize code like the above case I would use dynamic methods. And the performance difference between the two would be drastic.
Of course, keep in mind we're entering the zone of advanced code that's more complex and harder to read for the sake of performance. You could consider this overly optimized and overkill in code that isn't performance critical.
But in code that I write I avoid reflection like the plague.
My favourite way to things like that is to use expression trees. You can manually construct your expression tree to just create a new instance of your type and compile this expression tree into a delegate. The beauty of this approach is that you only need reflection and dynamic code generation for once and afterwards you work with the generated delegate. Also, the expression compiler does its best to work even on partial trusted environments, where dynamic methods are problematic. On the other hand, you have an abstraction layer much higher than writing pure IL code in an ILGenerator, which would be the way to go in a dynamic method.

C# - Passing all the method arguments to another method?

I've got a class, which has three overloaded methods. Let's say, there is:
class MyChildClass
{
public void myMethod(int i)
{ /* do something with i */ }
public void myMethod(int a, string b)
{ /* get i from a and b and call: */ myMethod(i); }
public void myMethod(string c, string d)
{ /* get i from c and d and call: */ myMethod(i); }
}
Now I'd like this class to be a private field in other (parent) class, but I need those three methods to be accessible. For now, I just did:
class MyBaseClass
{
private MyChildClass myObject = new myChildClass(); // or similar
public void myMethod(int i)
{ myObject.myMethod(i); }
public void myMethod(int a, string b)
{ myObject.myMethod(a, b); }
public void myMethod(string c, string s)
{ myObject.myMethod(c, d); }
}
Is there a way to implement it as one short method? Something which would look like:
public void myMethod(unknownListOfArgumentsOfDifferentTypes args)
{ myObject.myMethod(args); }
I tried to use public void myMethod(params object[] something) but it didn't work. Is it possible, or do I have to "project" every method into another?
EDIT: Child class has various methods and fields, which I want to be accessible for parent class only. That's why I don't want parent to derive after it. I didn't explain that, sorry if it looked like child class contains only those three methods. Those are the methods I want to be accessible as public methods of parent class.
Why don't you do
class MyChildClass : MyBaseClass
{
}
same effect, less code, and this way MyChildClass is a MyBaseClass
If you implement some sort of generic facade using reflection you'll just be reducing performance, bypassing the benefits of type safety and delaying the discovery of problems.
You'll also have have a "has a" relationship instead "is a" relationship which is incongruent with your class names.
If you want to give up this simplicty with its associated benefits you could make use the GetMethodBySig extension accepted in this post.
Something like this,
class SemiGenericFacade<T> where T : new()
{
private readonly t = new T();
public void CallVoidOnT(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodBySig(typeof(void), paramTypes)
.Single(mi => mi.Name == name);
match.Invoke(this.t, parameters);
}
}
Following on from Piotr Justyna's comment, implementing and using this method results in the cat turning into a tiger and eating her kittens.
If you were to do this it would make sense to add to the linked extension
public static class Extensions
{
public static MethodInfo GetMethodByNameThenSig(
this Type type,
string name,
Type returnType,
params Type[] parameterTypes)
{
return type.GetMethods().Where((m) =>
{
if (m.Name != name)
{
return false;
}
if (m.ReturnType != returnType)
{
return false;
}
var parameters = m.GetParameters();
if ((parameterTypes == null || parameterTypes.Length == 0))
{
return parameters.Length == 0;
}
if (parameters.Length != parameterTypes.Length)
{
return false;
}
for (int i = 0; i < parameterTypes.Length; i++)
{
if (parameters[i].ParameterType != parameterTypes[i])
{
return false;
}
}
return true;
}).Single();
}
}
Which you could use like this,
class GenericFacade<T> where T : new()
{
private readonly t = new T();
public void CallOnInternal(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodByNameThenSig(
name,
typeof(void),
paramTypes);
match.Invoke(this.t, parameters);
}
public TResult CallOnInternal<TResult>(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodByNameThenSig(
name,
typeof(TResult),
paramTypes);
return (TResult)match.Invoke(this.t, parameters);
}
}
FINAL EDIT
Looking at the code involved to use reflection and considering the cost associated with the loss of type safety. I'd suggest its better to establish the "has-a" relationship explicitly in the traditional manner.
You can use public void myMethod(params object[] something) as in:
public static void Main()
{
UnknownArgumentsMethod1(1, 2, 3, "foo");
}
public static void UnknownArgumentsMethod1(params object[] list)
{
UnknownArgumentsMethod2(list);
}
public static void UnknownArgumentsMethod2(params object[] list)
{
foreach (object o in list)
{
if (o.GetType() == typeof(int))
{
Console.WriteLine("This is an integer: " + (int)o);
}
else if (o.GetType() == typeof(string))
{
Console.WriteLine("This is a string: " + (string)o);
}
}
}
The obvious answer would be to have inheritance.
In your case (even though the names of the classes suggest otherwise) the way to do it is by inheriting the ChildClass in the BaseClass and that way you would have the methods from the ChildClass exposed through the BaseClass.
ex:
class MyBaseClass: MyChildClass
{
}
If the classes are not related and you just want to have an instance of MyChildClass in MyBaseClass but only expose a certain set of methods but by not making the others private what you could do is expose the MyChildClass instance through an interface that only exposes the necessary fields like so:
public class BaseClass
{
public IChildClass ChildClassInstance = new ChildClass();
}
public class ChildClass : IChildClass
{
public void myMethod(int i)
{ /* do something with i */ }
public void myMethod(int a, string b)
{ /* get i from a and b and call: */ myMethod(i); }
public void myMethod(string c, string d)
{ /* get i from c and d and call: */ myMethod(i); }
}
public interface IChildClass
{
void myMethod(int i);
void myMethod(int a, string b);
}
and then you could access only the methods that you allow to be exposed through an instance of the base class:
BaseClass test = new BaseClass();
test.ChildClassInstance.myMethod(1);
test.ChildClassInstance.myMethod(1,"test");

Categories