Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何存储类型a和运行时函数之间的映射<;A、 B>;类型转换? 将类型A的对象映射到类似类型A的运行时`_C#_Generics_Reflection_Code Generation_Linq Expressions - Fatal编程技术网

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