Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.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#中,是从派生类复制的吗?_C#_.net_C# 4.0 - Fatal编程技术网

我能实现';复制构造函数';在C#中,是从派生类复制的吗?

我能实现';复制构造函数';在C#中,是从派生类复制的吗?,c#,.net,c#-4.0,C#,.net,C# 4.0,用一个特定于应用程序的示例来说明我眼前的问题: 我有一个元数据提供程序类,具有以下(节略)接口: public class CtsDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider { protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type container

用一个特定于应用程序的示例来说明我眼前的问题:

我有一个元数据提供程序类,具有以下(节略)接口:

public class CtsDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        return metadata;
    }
}
我可以为
ExtendedModelMetadata
创建一个构造函数,该构造函数接受
ModelMetadata
参数,并将其所有属性显式分配给正在构造的实例,但我希望使用更通用、更少硬编码的方法。我能做什么?

您可以使用来实现这一点

Mapper.CreateMap<ModelMetaData , ExtendedModelMetadata>();
Mapper.CreateMap();

.NET Framework不提供深度复制功能。

如果可能的话,我将拆分创建和填充

public class CtsDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var extended = new ExtendedModelMetadata();
        PopulateMetadata(extended, attributes, containerType, modelAccessor, modelType, propertyName);

        return extended ;
    }

    protected override void PopulateMetadata(ModelMetaData data, IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
         base.PopulateMetaData(data, attributes, containerType, modelAccessor, modelType, propertyName);

        //populate extended properties.
    }
}
公共类CtsDataAnnotationsModelMetadataProvider:DataAnnotationsModelMetadataProvider
{
受保护的重写ModelMetadata CreateMatadata(IEnumerable属性、类型containerType、Func modelAccessor、类型modelType、字符串propertyName)
{
var extended=新的ExtendedModelMetadata();
PopulateMetadata(扩展、属性、containerType、modelAccessor、modelType、propertyName);
回报延长;
}
受保护的重写void PopulateMetadata(ModelMetaData数据、IEnumerable属性、类型containerType、Func modelAccessor、类型modelType、字符串propertyName)
{
PopulateMetaData(数据、属性、containerType、modelAccessor、modelType、propertyName);
//填充扩展属性。
}
}

您可以使用反射和泛型(这是一个廉价的、自行开发的示例,复制了所有字段,为了简洁起见,它做了很多假设):

类程序
    {
静态void Main(字符串[]参数)
        {
基b=新基();
b.数字=42;
派生d=副本(b);
Console.Read();
        }
静态t派生副本(TBase b)
其中t派生:TBase,new()
        {
TDerived=新的TDerived();
var b类型=类型(TBase);
var bFields=bType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            
foreach(bFields中的var字段)
            {
object val=field.GetValue(b);
字段设置值(d,val);
            }
返回d;
        }
    }
阶级基础
    {
公共整数{get;set;}
    }
派生类:基
    {
公共字符串名称{get;set;}
    }
这假设该类型有一个默认的无参数构造函数,但您知道了


或者,如果性能是一个问题,您可以创建一个代码生成器,使用分部类对赋值代码进行编码。

这就是
AutoMapper
所做的。@Aliostad不知道,从未使用过AutoMapper。在你发布答案时,我正在对其进行编码。就我个人而言,对于这么小的东西,我会自己滚来滚去,以避免产生依赖关系。@Aliostad在这种情况下,如果代码不太依赖于其他内部内容,我可能会直接从Auto Mapper中取出代码。但是我仍然会避免像复制构造函数这样简单的东西依赖于ORM框架。。。而且它很小。但同样,每个人都会做出自己的选择。@Aliostad是的,我可以想象它完全起作用,而我5分钟的例子说明了什么是可能做到的,但并没有。。。萝莉喜欢那样。我已经用基于AutoMapper的填充方法实现了这个策略,作为一个临时解决方案。我已经在使用AutoMapper了,我很喜欢它,但是我更喜欢没有非.NET依赖的东西。我实现了一个非常简洁、快速的临时AutoMapper解决方案,但可能会坚持下去。我知道这篇文章已经很老了,但我也遇到了类似的情况,找到了一个解决方案来解决您试图做的事情,如果您感兴趣,请查看答案:
public class CtsDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var extended = new ExtendedModelMetadata();
        PopulateMetadata(extended, attributes, containerType, modelAccessor, modelType, propertyName);

        return extended ;
    }

    protected override void PopulateMetadata(ModelMetaData data, IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
         base.PopulateMetaData(data, attributes, containerType, modelAccessor, modelType, propertyName);

        //populate extended properties.
    }
}
    class Program
    {
        static void Main(string[] args)
        {
            Base b = new Base();
            b.Number = 42;

            Derived d = Copy<Derived, Base>(b);
            Console.Read();
        }

        static TDerived Copy<TDerived, TBase>(TBase b)
            where TDerived : TBase, new()
        {
            TDerived d = new TDerived();

            var bType = typeof(TBase);
            var bFields = bType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            
            foreach (var field in bFields)
            {
                object val = field.GetValue(b);
                field.SetValue(d, val);
            }

            return d;
        }
    }

    class Base
    {
        public int Number { get; set; }
    }

    class Derived : Base
    {
        public string Name { get; set; }
    }