构建表达式树以调用具有 1 个或 2 个参数的函数
Build expression tree to call function with 1 or 2 parameters
因此,对表达式树进行一些试验。
想法是这样的:我想要 return 一个 Func<long, byte?, object>
对象。
根据我要使用该函数的类型,我将使用以下两种方法之一:LoadById(long, byte?)
或 LoadByID(long)
。既return一个对象。
所以我正在尝试执行以下操作:
根据类型是否实现某个接口,我使用
classToUseFunctionOn.LoadById(long, byte?)
或 classToUseFunctionOn.LoadByID(long)
。
所以,基本上我想要 returned 如果它实现了接口: (long id, byte? options) => new TestFacade().LoadById(id, options) and (long id, byte?选项)=> 新的 TestFacade().LoadByID(id)。
我只是不知道该怎么做。最后几行出错了。 Lambda 调用指出参数数量不正确。
以下是我目前的代码:
private static Func GetDataExtractorForTypeWithId(Type type)
{
var paramId = Expression.Parameter(typeof(long), "id");
ParameterExpression paramOptions = null;
//gets the ConstructorInfo for the constructor of type T with a single parameter of type IDataReader
var facadetype = GetFacadeType(type.Name);
MethodInfo loadMethod;
var linkedEntitiesInterface = facadetype.GetInterface(typeof(IFacadeLoadLinkedEntities).Name);
var lamdaParameterExpressions = new List() { paramId };
if (linkedEntitiesInterface != null)
{
loadMethod = facadetype.GetMethod("LoadById");
paramOptions = Expression.Parameter(linkedEntitiesInterface.GetGenericTypeDefinition().GenericTypeArguments[1], "options");
lamdaParameterExpressions.Add(paramOptions);
}
else
{
paramOptions = Expression.Parameter(typeof(byte?));
loadMethod = facadetype.GetMethod("LoadByID", new Type[1]{typeof(long)});
}
var facadeConstructor = facadetype.GetConstructor(new Type[0]);
var newFacade = Expression.New(facadeConstructor);
var callLoad = Expression.Call(newFacade, loadMethod, lamdaParameterExpressions);
lamdaParameterExpressions.Add(paramOptions);
var returnValue = Expression.Parameter(typeof(object));
lamdaParameterExpressions.Add(returnValue);
var entityVariable = Expression.Variable(typeof(object), "entity");
Expression.Assign(entityVariable, callLoad);
var lambda = Expression.Lambda>(
entityVariable, lamdaParameterExpressions.ToArray());
//compiles the Expression to a usable delegete.
return lambda.Compile();
}
与此同时,我找到了让它工作的方法:
private static Func GetDataExtractorForTypeWithId(Type type)
{
var paramId = Expression.Parameter(typeof(long), "id");
ParameterExpression paramOptions = null;
var facadetype = GetFacadeType(type.Name) ?? typeof(AzzFacade).MakeGenericType(type);
MethodInfo loadMethod;
var linkedEntitiesInterface = facadetype.GetInterface(typeof(IFacadeLoadLinkedEntities).Name);
if (linkedEntitiesInterface != null)
{
loadMethod = facadetype.GetMethod("LoadById");
paramOptions = Expression.Parameter(typeof(byte), "options");
}
else
{
paramOptions = Expression.Parameter(typeof(byte));
loadMethod = facadetype.GetMethod("LoadByID", new Type[1]{typeof(long)});
}
var facadeConstructor = facadetype.GetConstructor(new Type[0]);
if(facadeConstructor==null)
throw new NullReferenceException($"No parameterless constructor found for facade for type {type.Name}");
MethodCallExpression callLoad;
var newFacade = Expression.New(facadeConstructor);
if (linkedEntitiesInterface != null)
{
var conversionExpression = Expression.Convert(paramOptions, linkedEntitiesInterface.GetGenericArguments()[1]);
// ReSharper disable once AssignNullToNotNullAttribute
callLoad = Expression.Call(newFacade, loadMethod, paramId, conversionExpression);
}
else
{
// ReSharper disable once AssignNullToNotNullAttribute
callLoad = Expression.Call(newFacade, loadMethod, paramId);
}
var lambda = Expression.Lambda>(
// ReSharper disable once AssignNullToNotNullAttribute
callLoad, paramId, paramOptions);
//compiles the Expression to a usable delegate.
return lambda.Compile();
}
因此,对表达式树进行一些试验。
想法是这样的:我想要 return 一个 Func<long, byte?, object>
对象。
根据我要使用该函数的类型,我将使用以下两种方法之一:LoadById(long, byte?)
或 LoadByID(long)
。既return一个对象。
所以我正在尝试执行以下操作:
根据类型是否实现某个接口,我使用
classToUseFunctionOn.LoadById(long, byte?)
或 classToUseFunctionOn.LoadByID(long)
。
所以,基本上我想要 returned 如果它实现了接口: (long id, byte? options) => new TestFacade().LoadById(id, options) and (long id, byte?选项)=> 新的 TestFacade().LoadByID(id)。
我只是不知道该怎么做。最后几行出错了。 Lambda 调用指出参数数量不正确。
以下是我目前的代码:
private static Func GetDataExtractorForTypeWithId(Type type)
{
var paramId = Expression.Parameter(typeof(long), "id");
ParameterExpression paramOptions = null;
//gets the ConstructorInfo for the constructor of type T with a single parameter of type IDataReader
var facadetype = GetFacadeType(type.Name);
MethodInfo loadMethod;
var linkedEntitiesInterface = facadetype.GetInterface(typeof(IFacadeLoadLinkedEntities).Name);
var lamdaParameterExpressions = new List() { paramId };
if (linkedEntitiesInterface != null)
{
loadMethod = facadetype.GetMethod("LoadById");
paramOptions = Expression.Parameter(linkedEntitiesInterface.GetGenericTypeDefinition().GenericTypeArguments[1], "options");
lamdaParameterExpressions.Add(paramOptions);
}
else
{
paramOptions = Expression.Parameter(typeof(byte?));
loadMethod = facadetype.GetMethod("LoadByID", new Type[1]{typeof(long)});
}
var facadeConstructor = facadetype.GetConstructor(new Type[0]);
var newFacade = Expression.New(facadeConstructor);
var callLoad = Expression.Call(newFacade, loadMethod, lamdaParameterExpressions);
lamdaParameterExpressions.Add(paramOptions);
var returnValue = Expression.Parameter(typeof(object));
lamdaParameterExpressions.Add(returnValue);
var entityVariable = Expression.Variable(typeof(object), "entity");
Expression.Assign(entityVariable, callLoad);
var lambda = Expression.Lambda>(
entityVariable, lamdaParameterExpressions.ToArray());
//compiles the Expression to a usable delegete.
return lambda.Compile();
}
与此同时,我找到了让它工作的方法:
private static Func GetDataExtractorForTypeWithId(Type type)
{
var paramId = Expression.Parameter(typeof(long), "id");
ParameterExpression paramOptions = null;
var facadetype = GetFacadeType(type.Name) ?? typeof(AzzFacade).MakeGenericType(type);
MethodInfo loadMethod;
var linkedEntitiesInterface = facadetype.GetInterface(typeof(IFacadeLoadLinkedEntities).Name);
if (linkedEntitiesInterface != null)
{
loadMethod = facadetype.GetMethod("LoadById");
paramOptions = Expression.Parameter(typeof(byte), "options");
}
else
{
paramOptions = Expression.Parameter(typeof(byte));
loadMethod = facadetype.GetMethod("LoadByID", new Type[1]{typeof(long)});
}
var facadeConstructor = facadetype.GetConstructor(new Type[0]);
if(facadeConstructor==null)
throw new NullReferenceException($"No parameterless constructor found for facade for type {type.Name}");
MethodCallExpression callLoad;
var newFacade = Expression.New(facadeConstructor);
if (linkedEntitiesInterface != null)
{
var conversionExpression = Expression.Convert(paramOptions, linkedEntitiesInterface.GetGenericArguments()[1]);
// ReSharper disable once AssignNullToNotNullAttribute
callLoad = Expression.Call(newFacade, loadMethod, paramId, conversionExpression);
}
else
{
// ReSharper disable once AssignNullToNotNullAttribute
callLoad = Expression.Call(newFacade, loadMethod, paramId);
}
var lambda = Expression.Lambda>(
// ReSharper disable once AssignNullToNotNullAttribute
callLoad, paramId, paramOptions);
//compiles the Expression to a usable delegate.
return lambda.Compile();
}