C# 如何调用反射函数<;T、 T>;使用表达式树的属性
我有一个泛型类,其lambda属性定义如下:C# 如何调用反射函数<;T、 T>;使用表达式树的属性,c#,linq-expressions,C#,Linq Expressions,我有一个泛型类,其lambda属性定义如下: public class Transformation<TProperty> : TransformationBase { public Func<TProperty, TProperty> Transform { get; private set; } ... 因此,以手写为例,其中TProperty是string,它应该是: Foo foo = ... // coming from an exte
public class Transformation<TProperty> : TransformationBase
{
public Func<TProperty, TProperty> Transform { get; private set; }
...
因此,以手写为例,其中TProperty是string,它应该是:
Foo foo = ... // coming from an external source
Transformation<string> tranformation = ... // coming from an external source
foo.Value = transformation.Transform((string)foo.Value);
Foo-Foo=…//来自外部来源
转换转换=…//来自外部来源
foo.Value=transformation.Transform((字符串)foo.Value);
除了我不知道转换的确切类型,因为它是在外部程序集中定义的。因此,它可以是int或其他形式,而不是string。这就是为什么我想使用表达式树为给定的转换编译操作,以便调用:
Foo foo = ... // coming from an external source
TransformationBase transformation = ... // coming from an external source
Action<Foo> transform = Compile(transformation);
transform(foo); // should transform foo.Value using the Transform property of 'transformation'
Foo-Foo=…//来自外部来源
TransformationBase转换=…//来自外部来源
动作转换=编译(转换);
变换(foo);//应使用“transformation”的transform属性转换foo.Value
注意:我让Transformation继承自TransformationBase,以澄清此讨论。不确定您想做什么,但如果我理解您的意图,我认为没有必要编译
表达式:
private static Action<TProperty> Compile<TProperty>(Transformation<TProperty> transformation)
{
return new Action<TProperty>(p => transformation.Transform(p));
}
私有静态操作编译(转换)
{
返回新操作(p=>transformation.Transform(p));
}
看一个例子,它应该会给你想要的
void Main()
{
var dummyObject = new Dummy { Test = "Hello!" };
var propertyTransform = Create(dummyObject, "Test");
propertyTransform(dummyObject);
Console.WriteLine("Final transformation " + dummyObject.Test);
}
class Dummy {
public string Test { get; set; }
}
// Define other methods and classes here
public class Transformation<TProperty>
{
public Func<TProperty, TProperty> Transform { get; set; }
}
public static Action<TObj> Create<TObj>(TObj myObject, string property){
var prop = myObject
.GetType()
.GetProperty(property);
var val = prop.GetValue(myObject);
var transformation = Create((dynamic)val);
var transform = transformation.Transform;
return obj => {
var newValue = transform((dynamic)val);
prop.SetValue(myObject, newValue);
};
}
public static Transformation<TProperty> Create<TProperty>(TProperty property){
var transformation = new Transformation<TProperty>();
// just a dummy hijacking.
if(typeof(TProperty)==typeof(string)){
Func<string, string> test = input => "I am changed man!";
transformation.Transform = (dynamic)test;
}
return transformation;
}
void Main()
{
var dummyObject=newdummy{Test=“Hello!”};
var propertyTransform=创建(dummyObject,“测试”);
属性转换(dummyObject);
Console.WriteLine(“最终转换”+dummObject.Test);
}
类虚拟{
公共字符串测试{get;set;}
}
//在此处定义其他方法和类
公共阶级转型
{
公共Func变换{get;set;}
}
公共静态操作创建(TObj myObject,字符串属性){
var prop=myObject
.GetType()
.GetProperty(property);
var val=属性GetValue(myObject);
var转换=创建((动态)val);
var transform=transform.transform;
返回obj=>{
var newValue=转换((动态)val);
属性设置值(myObject,newValue);
};
}
公共静态转换创建(TProperty属性){
var转换=新转换();
//只是一次假劫持。
if(typeof(TProperty)=typeof(string)){
Func test=input=>“我变了!”;
Transform=(动态)测试;
}
回报转化;
}
输出:
最后的转变我变了代码>
你的问题更多地与你的问题周围没有打字有关Foo.Value
是松散类型的,但是您的转换函数是强类型的。表达式树也是强类型的。使用它们不允许您以松散类型的方式神奇地调用代码
解决方案要么是大量的反射,要么是一些简单的动态:
编辑:我添加了CompileUnited,它使用ExpressionTrees。我还添加了CompileReflection,它使用反射而不使用ExpressionTrees。我推荐使用dynamic的。它是迄今为止最容易阅读的,因此也是最容易维护的
class Program
{
static void Main(string[] args)
{
var testTransform = new Transformation<string>
{
Transform = s => s.ToUpper()
};
var a = Compile(testTransform);
var foo = new Foo
{
Value = "test"
};
a(foo);
//foo.Value is now TEST
}
public static Action<Foo> CompileReflection(TransformationBase transformation)
{
var f = transformation
.GetType()
.GetProperty("Transform")
.GetGetMethod()
.Invoke(transformation, null) as Delegate;
return foo => foo.Value = f.DynamicInvoke(foo.Value);
}
public static Action<Foo> Compile(TransformationBase transformation)
{
return new Action<Foo>(f =>
{
dynamic d = f.Value;
dynamic t = transformation;
f.Value = t.Transform(d);
});
}
public static Action<Foo> CompileUntyped(TransformationBase transformation)
{
var transformType = transformation.GetType();
var genericType = transformType.GetGenericArguments().First();
var fooParam = Expression.Parameter(typeof(Foo), "f");
var valueGetter = typeof(Foo).GetProperty("Value").GetGetMethod();
var valueSetter = typeof(Foo).GetProperty("Value").GetSetMethod();
var transformFuncMember = transformType.GetProperty("Transform").GetGetMethod();
//Equivalent to f => f.Value = transformation.Transform((T)f.Value)
//Where T is the generic type parameter of the Transformation, and f is of type Foo
var expression = Expression.Lambda<Action<Foo>>(
Expression.Call(
fooParam,
valueSetter,
Expression.Invoke(
Expression.Property(
Expression.Constant(transformation, transformType),
transformFuncMember
),
Expression.Convert(
Expression.Property(fooParam, valueGetter),
genericType
)
)
), fooParam
);
return expression.Compile();
}
}
public class TransformationBase { }
public class Transformation<TProperty> : TransformationBase
{
public Func<TProperty, TProperty> Transform { get; set; }
}
public class Foo
{
public object Value { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
var testTransform=新转换
{
Transform=s=>s.ToUpper()
};
var a=编译(testTransform);
var foo=新foo
{
Value=“测试”
};
a(foo);
//值现在是TEST
}
公共静态操作编译器反射(TransformationBase转换)
{
var f=变换
.GetType()
.GetProperty(“转换”)
.getMethod()
.作为委托调用(转换,null);
返回foo=>foo.Value=f.DynamicInvoke(foo.Value);
}
公共静态操作编译(TransformationBase转换)
{
返回新操作(f=>
{
动态d=f.值;
动态t=变换;
f、 值=t.变换(d);
});
}
公共静态操作编译器已启用(TransformationBase转换)
{
var transformType=transformation.GetType();
var genericType=transformType.GetGenericArguments().First();
var fooParam=Expression.Parameter(typeof(Foo),“f”);
var valueGetter=typeof(Foo).GetProperty(“值”).getMethod();
var valueSetter=typeof(Foo).GetProperty(“值”).GetSetMethod();
var transformFuncMember=transformType.GetProperty(“Transform”).GetMethod();
//等价于f=>f.Value=transformation.Transform((T)f.Value)
//其中T是转换的泛型类型参数,f是Foo类型
var expression=expression.Lambda(
表情,打电话(
fooParam,
估价师,
表达式.调用(
表达式.属性(
表达式.常量(转换,转换类型),
转换函数成员
),
表达式。转换(
Expression.Property(fooParam,valueGetter),
泛型
)
)
),fooParam
);
返回表达式.Compile();
}
}
公共类转换基{}
公共类转换:TransformationBase
{
公共Func变换{get;set;}
}
公开课Foo
{
公共对象值{get;set;}
}
我不太明白这个问题。Foo
和TProperty
之间有什么关系?转换
和转换
之间有什么关系?Compile
方法是否在Transformation
类上?使用表达式树是一项要求,还是仅仅是您的att方式
void Main()
{
var dummyObject = new Dummy { Test = "Hello!" };
var propertyTransform = Create(dummyObject, "Test");
propertyTransform(dummyObject);
Console.WriteLine("Final transformation " + dummyObject.Test);
}
class Dummy {
public string Test { get; set; }
}
// Define other methods and classes here
public class Transformation<TProperty>
{
public Func<TProperty, TProperty> Transform { get; set; }
}
public static Action<TObj> Create<TObj>(TObj myObject, string property){
var prop = myObject
.GetType()
.GetProperty(property);
var val = prop.GetValue(myObject);
var transformation = Create((dynamic)val);
var transform = transformation.Transform;
return obj => {
var newValue = transform((dynamic)val);
prop.SetValue(myObject, newValue);
};
}
public static Transformation<TProperty> Create<TProperty>(TProperty property){
var transformation = new Transformation<TProperty>();
// just a dummy hijacking.
if(typeof(TProperty)==typeof(string)){
Func<string, string> test = input => "I am changed man!";
transformation.Transform = (dynamic)test;
}
return transformation;
}
class Program
{
static void Main(string[] args)
{
var testTransform = new Transformation<string>
{
Transform = s => s.ToUpper()
};
var a = Compile(testTransform);
var foo = new Foo
{
Value = "test"
};
a(foo);
//foo.Value is now TEST
}
public static Action<Foo> CompileReflection(TransformationBase transformation)
{
var f = transformation
.GetType()
.GetProperty("Transform")
.GetGetMethod()
.Invoke(transformation, null) as Delegate;
return foo => foo.Value = f.DynamicInvoke(foo.Value);
}
public static Action<Foo> Compile(TransformationBase transformation)
{
return new Action<Foo>(f =>
{
dynamic d = f.Value;
dynamic t = transformation;
f.Value = t.Transform(d);
});
}
public static Action<Foo> CompileUntyped(TransformationBase transformation)
{
var transformType = transformation.GetType();
var genericType = transformType.GetGenericArguments().First();
var fooParam = Expression.Parameter(typeof(Foo), "f");
var valueGetter = typeof(Foo).GetProperty("Value").GetGetMethod();
var valueSetter = typeof(Foo).GetProperty("Value").GetSetMethod();
var transformFuncMember = transformType.GetProperty("Transform").GetGetMethod();
//Equivalent to f => f.Value = transformation.Transform((T)f.Value)
//Where T is the generic type parameter of the Transformation, and f is of type Foo
var expression = Expression.Lambda<Action<Foo>>(
Expression.Call(
fooParam,
valueSetter,
Expression.Invoke(
Expression.Property(
Expression.Constant(transformation, transformType),
transformFuncMember
),
Expression.Convert(
Expression.Property(fooParam, valueGetter),
genericType
)
)
), fooParam
);
return expression.Compile();
}
}
public class TransformationBase { }
public class Transformation<TProperty> : TransformationBase
{
public Func<TProperty, TProperty> Transform { get; set; }
}
public class Foo
{
public object Value { get; set; }
}