Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.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# 多态方法的Type.GetMethod()(泛型和非泛型)_C#_Reflection - Fatal编程技术网

C# 多态方法的Type.GetMethod()(泛型和非泛型)

C# 多态方法的Type.GetMethod()(泛型和非泛型),c#,reflection,C#,Reflection,我目前正在创建一种自定义的深度复制对象的方法。我使用一个静态类来实现这个功能 public static class CopyServer { public static int CopyDeep(int original) { return original; } //not shown: same for all other value types I use (long, float,...) public static T C

我目前正在创建一种自定义的深度复制对象的方法。我使用一个静态类来实现这个功能

public static class CopyServer
{

    public static int CopyDeep(int original)
    {
        return original;
    }
    //not shown: same for all other value types I use (long, float,...)


    public static T CopyDeep<T>(T original) where T: ICopyAble
    {
        if (original == null)
            return default;
        if (original is ICopyAutofields)
            return CopyAutofields(original);
        return (T)original.CopyDeep();
    }

    private static T CopyAutofields<T>(T original)
    {
        Delegate del;
        if (!_copyFunctions.TryGetValue(typeof(T), out del))
        {
            //not shown: Building expression for parameter etc.
            foreach (var fieldInfo in typeof(T).GetFields())
            {
                //not shown: checking options set by custom attributes

                MethodInfo methodInfo = typeof(CopyServer).GetMethod("CopyDeep", new[] { fieldInfo.FieldType });
                //I can't remove the second param without getting an AmbiguousMatchException

                if (methodInfo == null)
                {
                    throw new Exception($"CopyDeep not defined for type {fieldInfo.FieldType}");
                }

                if (methodInfo.IsGenericMethod)
                    methodInfo = methodInfo.MakeGenericMethod(fieldInfo.FieldType);

                Expression call = Expression.Call(methodInfo, readValue);

                //not shown: Assign Expression

            }

            //not shown: return Expression and compiling
        }
        return ((Func<T, T>)del)(original);
    }
}
公共静态类CopyServer
{
公共静态int-copydeph(int-original)
{
归还原件;
}
//未显示:与我使用的所有其他值类型相同(长、浮点等)
公共静态T copydeph(T original),其中T:ICopyAble
{
如果(原始==null)
返回默认值;
如果(原始为ICopyAutofields)
返回CopyAutofields(原始);
返回(T)original.copydeph();
}
私有静态T CopyAutofields(T原始)
{
del代表;
if(!\u copyFunctions.TryGetValue(类型(T),out del))
{
//未显示:参数等的建筑表达式。
foreach(typeof(T).GetFields()中的var fieldInfo)
{
//未显示:检查由自定义属性设置的选项
MethodInfo MethodInfo=typeof(CopyServer).GetMethod(“CopyDeep”,新[]{fieldInfo.FieldType});
//我无法删除第二个参数而不获得含糊不清的MatchException
if(methodInfo==null)
{
抛出新异常($“未为类型{fieldInfo.FieldType}定义CopyDeep”);
}
if(methodInfo.IsGenericMethod)
methodInfo=methodInfo.MakeGenericMethod(fieldInfo.FieldType);
Expression call=Expression.call(methodInfo,readValue);
//未显示:指定表达式
}
//未显示:返回表达式和编译
}
申报表(原件);
}
}
我使用
T CopyAutofields
来构建函数(通过构建和编译表达式树),这样我就不必为我想要手动复制的每个类创建复制函数。我用自定义属性控制复制行为(我在上面的代码中留下了这一部分,因为它与我的问题无关)

只要只使用类型为非泛型函数的字段,代码就可以正常工作。但它无法检索我的通用函数
T CopyDeep

例如:

//This works:
public class Manager : ICopyAble,ICopyAutofields
{
    public string FirstName;
    public string LastName;
}

//This doesn't
//Meaning: typeof(CopyServer).GetMethod("copyDeep", new[] { fieldInfo.FieldType }); 
//in T copyAutofields<T> returns null for the Manager-field and my exception gets thrown
public class Employee : ICopyAble,ICopyAutofields
{
    public string FirstName;
    public string LastName;
    public Manager Manager;
}

//This is what I was using before I started using the ICopyAutofields. 
//This approach works, but its' too much too write since my classes usually 
//have way more than three fields and I occasionally forget to update 
//copyDeep()-function if I add new ones.
public class Employee : ICopyAble,ICopyAutofields
{
    public string FirstName;
    public string LastName;
    public Manager Manager;

    public IModable CopyDeep()
    {
        var result = new Employee();
        result.FirstName = CopyServer.copyDeep(FirstName);
        result.LastName= CopyServer.copyDeep(LastName);
        result.Manager= CopyServer.copyDeep(Manager);
        return result;
    }
}
//这是可行的:
公共类管理器:ICopyAble,ICopyAutofields
{
公共字符串名;
公共字符串LastName;
}
//这并不重要
//含义:typeof(CopyServer).GetMethod(“copyDeep”,new[]{fieldInfo.FieldType});
//在T copyAutofields中,Manager字段返回null,并引发我的异常
公共类雇员:可iCopy,iCopy自动字段
{
公共字符串名;
公共字符串LastName;
公共经理;
}
//这是我在开始使用ICopyAutofields之前使用的。
//这种方法是有效的,但由于我的类通常
//有三个以上的字段,我偶尔会忘记更新
//copyDeep()-如果我添加新的,则返回函数。
公共类雇员:可iCopy,iCopy自动字段
{
公共字符串名;
公共字符串LastName;
公共经理;
公共IModable CopyDeep()
{
var result=新员工();
result.FirstName=CopyServer.copydeph(FirstName);
result.LastName=CopyServer.copydeph(LastName);
result.Manager=CopyServer.copydeph(Manager);
返回结果;
}
}

长话短说:如果具有正确名称的泛型函数和非泛型函数都存在,我需要一种为类型T获取匹配函数的方法。

在.NET 4.7.1中,您需要使用方法并过滤结果:

class MyClass
{
    public T M<T>(T t) { return default(T); }
    public int M(int t) { return 0; }
}

var m = typeof(MyClass).GetMethod("M", new[] { typeof(string) }); // null
var m1 = typeof(MyClass).GetMethods()
    .Where(mi => mi.Name == "M" && mi.GetGenericArguments().Any())
    .First(); // returns generic method

深度克隆=序列化+反序列化。@Sinatr谢谢,但我需要更多的控制。这就是我使用属性的目的。例如,一些字段根本不会被复制(主键),而另一些字段有一个字段指示它们被复制的时间。这也需要设置。您也可以使用属性来控制序列化。@Sinatr这是正确的。我在其他地方使用序列化。但它不适合这里。顺便说一句,我强烈建议您遵循.NET命名约定,特别是对于像这样的公共示例代码。这意味着你所有的方法都应该是PascalCase,例如CopyDeep而不是CopyDeep。同样,我建议使用“香草”VisualStudio支撑样式(单独在一行上打开支撑)。这并不是说拥有自己喜欢的支撑风格是错误的,但它可能会让读者分心。非常感谢,这就是我想要的。
public static class CopyAutoFieldServer<T>
{
    public static T copyAutofields(T original) { ... }
}