I have lots of sub classes, inherited from IDbTypeHandler<T>
,
and I want know how to convert "SetValue" to lambda expression, after that I can call Action<IDbDataParameter, object>
.
inteface
public interface IDbTypeHandler
{
}
public interface IDbTypeHandler<T> : IDbTypeHandler
{
void SetValue(IDbDataParameter parameter, T value);
}
classes
internal class UniqueidentifierUlIdHandler : IDbTypeHandler<UlId>
{
public void SetValue(IDbDataParameter parameter, UlId value)
{
parameter.Value = value.ToByteArray();
}
}
internal class Char1Handler : IDbTypeHandler<bool>
{
public void SetValue(IDbDataParameter parameter, bool value)
{
parameter.Value = value;
}
}
---------------update------------------
the follow code is where i want to make a lambda expression
if (!TryGetValue("Key", out IDbTypeHandler dbTypeHandler))
{
return false;
}
var t = dbTypeHandler.GetType();
var itf = t.GetInterfaces().SingleOrDefault(i => i.IsGenericType);
var xx = itf.GenericTypeArguments[0];
var p0 = Expression.Parameter(t);
var p1 = Expression.Parameter(typeof(IDbDataParameter));
var p2 = Expression.Parameter(xx);
var method = t.GetMethod("SetValue");
Type delegateType = typeof(Action<,,>).MakeGenericType(t, typeof(IDbDataParameter), xx);
var lambda = Expression.Lambda(delegateType, Expression.Call(p0, method, p1, p2), new[] { p0, p1, p2 });
now, i get a lambda. if i use .Compile()
, then it will return a Delegate
type. But, i want a Action<IDbDataParameter,object>
I know i need a type convert before var lambda = Expression.Lambda
, but i don't know what to do for now.
I have recreated a little sample with 2 ways to implement lambda (see classes test1
and test2
)
internal class Program
{
static void Main(string[] args)
{
var one = new One();
var two = new Two();
var obj_int = new ClassX();
var obj_str = new ClassX();
var ActOne = new test1<int, One>();
var ActTwo = new test1<string, Two>();
ActOne.myLambda1(obj_int, 10, one);
ActTwo.myLambda1(obj_str, "Youpi", two);
Console.WriteLine($"one = {obj_int.Value} two = {string.Join(",",(char[])obj_str.Value)}");
new test2<int, One>().myLambda2(obj_int, 20);
new test2<string, Two>().myLambda2(obj_str, "Super");
Console.WriteLine($"one = {obj_int.Value} two = {string.Join(",", (char[])obj_str.Value)}");
}
}
//lambda with U instantiated
public class test1<T,U> where U : ITest<T>
{
public Action<ClassX, T, U> myLambda1 = (arg1, arg2, arg3) =>
{
arg3.SetValue(arg1, arg2);
};
}
//lambda with U not instantiated
public class test2<T, U> where U : ITest<T> , new()
{
public Action<ClassX, T> myLambda2 = (arg1, arg2) =>
{
new U().SetValue(arg1, arg2);
};
}
public class ClassX
{
public object Value;
}
public interface ITest<T>
{
void SetValue(ClassX parameter, T value);
}
public class One : ITest<int>
{
public void SetValue(ClassX parameter, int value)
{
parameter.Value = value + 10;
}
}
public class Two : ITest<string>
{
public void SetValue(ClassX parameter, string value)
{
parameter.Value = value.ToCharArray();
}
}
result:
one = 20 two = Y,o,u,p,i
one = 30 two = S,u,p,e,r