我可以在C#中实现从派生类复制的“复制构造函数”吗?

一个应用程序特定示例来说明我的直接问题:

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

public class CtsDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider { protected override ModelMetadata CreateMetadata(IEnumerable attributes, Type containerType, Func modelAccessor, Type modelType, string propertyName) { var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); return metadata; } } 

现在我想扩展ModelMetadata以及其他属性,填充这些属性并返回和ExtendedModelMetadata实例。 如何通过扩展实例中的base.CreateMetadata很好地传达分配给metadata实例的base.CreateMetadata ? 我想要但却没有的是;

 var metadata = (ExtendedModelMetadata)base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); 

我可以为ExtendedModelMetadata创建一个构造函数,它接受一个ModelMetadata参数并显式地将它的所有属性分配给正在构造的实例,但我想要一个更通用且不太硬编码的方法。 我能做什么?

您可以使用AutoMapper来实现此目的。

 Mapper.CreateMap(); 

.NET Framework不提供深层复制function。

你可以使用reflection和generics(这是一个廉价的,本土的例子,复制所有字段,为简洁起见做了很多假设):

  class Program  {    static void Main(string[] args)    {      Base b = new Base();      b.Number = 42;      Derived d = Copy(b);      Console.Read();    }    static TDerived Copy(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; }  } 

这假定该类型具有默认的无参数构造函数,但您明白了。

或者,如果性能是一个问题,您可以执行诸如创建代码生成器之类的操作,该代码生成器使用分部代码对分配代码进行编码。

如果可能的话,我会把创造和人口分开。

 public class CtsDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider { protected override ModelMetadata CreateMetadata(IEnumerable attributes, Type containerType, Func 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 attributes, Type containerType, Func modelAccessor, Type modelType, string propertyName) { base.PopulateMetaData(data, attributes, containerType, modelAccessor, modelType, propertyName); //populate extended properties. } }