C# 如何存储类型a和运行时函数之间的映射<;A、 B>;类型转换? 将类型A的对象映射到类似类型A的运行时`
使用C# 如何存储类型a和运行时函数之间的映射<;A、 B>;类型转换? 将类型A的对象映射到类似类型A的运行时`,c#,generics,reflection,code-generation,linq-expressions,C#,Generics,Reflection,Code Generation,Linq Expressions,使用System.Reflection在运行时发现类型列表 为每个适当的类型创建一个表达式表达式。该函数将oldType类型的对象转换为newType类型的对象 旁注: Func的泛型类型参数有些误导,感觉应该是Func,但类型在编译时未知: Expression<Func<object, object>> GetConvertExpression(Type oldType, Type newType) 编辑:我在午夜左右写下了原始答案。我想这说明了问题。听起来您最
System.Reflection在运行时发现类型列表
为每个适当的类型
创建一个表达式表达式
。该函数将oldType
类型的对象转换为newType
类型的对象
旁注:
Func
的泛型类型参数有些误导,感觉应该是Func
,但类型在编译时未知:
Expression<Func<object, object>> GetConvertExpression(Type oldType, Type newType)
编辑:我在午夜左右写下了原始答案。我想这说明了问题。听起来您最需要的是当参数和返回类型仅在运行时已知时如何构造委托。通过使用对象
可以解决此问题。您仍然可以使用强类型。最相关的电话是:
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(A), typeof(NewA));
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(A), typeof(NewA));
class Program
{
static void Main(string[] args)
{
var cv = new ConverterDictionary();
var type2_converter = cv.GetConverter<Type2, Type2_New>();
var converterF = type2_converter.Compile();
var type2 = new Type2 { Field1 = "Hello", Field2 = "World" };
var type2_New = converterF(type2);
}
}
public class ConverterDictionary
{
private Dictionary<Tuple<Type, Type>, object> conversionDict = new Dictionary<Tuple<Type, Type>, object>();
public ConverterDictionary()
{
var convertPairs = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.CustomAttributes.Any(a => a.AttributeType == typeof(ClassConvertAttribute)))
.Select(t => Tuple.Create(t, (Type)(t.CustomAttributes.First().NamedArguments[0].TypedValue.Value)))
.ToList();
foreach(var pair in convertPairs)
{
var fromType = pair.Item1;
var toType = pair.Item2;
var fieldConversions = fromType.GetFields()
.Where(f => f.CustomAttributes.Any(a => a.AttributeType == typeof(FieldConvertAttribute)))
.Select(f => Tuple.Create(f, toType.GetField((string)(f.CustomAttributes.First().NamedArguments[0].TypedValue.Value))))
.ToList();
var delegateType = typeof(Func<,>).MakeGenericType(fromType, toType);
var param1 = Expression.Parameter(fromType, "oldInst");
var returnVar = Expression.Variable(toType, "newInst");
var expr = Expression.Lambda(
delegateType,
Expression.Block(
new ParameterExpression[] { returnVar },
new Expression[]
{
Expression.Assign(
returnVar,
Expression.New(toType)
),
}.Concat(
fieldConversions.Select(fc =>
Expression.Assign(
Expression.MakeMemberAccess(
returnVar,
fc.Item2
),
Expression.MakeMemberAccess(
param1,
fc.Item1
)
)
)
).Concat(
new Expression[] { returnVar }
)
),
param1
);
conversionDict[pair] = expr;
}
}
public Expression<Func<TFrom, TTo>> GetConverter<TFrom, TTo>()
{
var key = Tuple.Create(typeof(TFrom), typeof(TTo));
if (conversionDict.ContainsKey(key))
return conversionDict[key] as Expression<Func<TFrom, TTo>>;
return null;
}
}
[ClassConvert(ToType=typeof(Type1_New))]
public class Type1
{
[FieldConvert(ToFieldName = "Field1")]
public string Field1;
}
[ClassConvert(ToType = typeof(Type2_New))]
public class Type2
{
[FieldConvert(ToFieldName="Field1")]
public string Field1;
[FieldConvert(ToFieldName = "Field2_New")]
public string Field2;
}
public class Type1_New
{
public string Field1;
}
public class Type2_New
{
public string Field1;
public string Field2_New;
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class ClassConvertAttribute : Attribute
{
public Type ToType { get; set; }
}
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class FieldConvertAttribute : Attribute
{
public string ToFieldName { get; set; }
}