2012-03-29 1 views
3

Eine anwendungsspezifische Beispiel mein unmittelbares Problem zu veranschaulichen:Kann ich in C# einen Kopierkonstruktor erstellen, der von einer abgeleiteten Klasse kopiert?

ich einen Metadaten-Anbieter Klasse mit der folgenden (verkürzt) Schnittstelle:

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

Jetzt würde ich ModelMetadata mit zusätzlichen Eigenschaften erweitern möchten, füllen diese und Rückkehr und Instanz von ExtendedModelMetadata. Wie kann ich Eigenschaften, die der metadata -Instanz von base.CreateMetadata in meiner erweiterten Instanz zugewiesen sind, schön vermitteln? Was ich möchte, aber nicht habe, ist;

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

kann ich einen Konstruktor für ExtendedModelMetadata erstellen, die einen ModelMetadata Parameter für diese und ausdrücklich ordnet alle seine Eigenschaften zum Beispiel so aufgebaut, aber ich möchte eine allgemeinere und weniger hart codiert Ansatz nimmt. Was kann ich tun?

+0

Ich weiß, dass dieser Beitrag ziemlich alt ist, aber ich war in einer ähnlichen Situation und fand eine Lösung für das, was Sie versuchten zu tun, überprüfen Sie die Antwort, wenn Sie neugierig sind: http://stackoverflow.com/questions/16627312/how-can-i-extend-dataannotationsmodelmetadata/16680163 # 16680163 – ppetrov

Antwort

3

Sie können AutoMapper verwenden, um dies zu erreichen.

Mapper.CreateMap<ModelMetaData , ExtendedModelMetadata>(); 

.NET Framework bietet keine Funktion für die Tiefenkopie.

+0

Ich benutze bereits AutoMapper, und liebe es, aber ich würde etwas ohne eine Nicht-Abhängigkeit bevorzugen. Ich habe eine sehr saubere und schnelle AutoMapper-Zwischenlösung implementiert und bleibe dabei. – ProfK

1

Ich würde Schöpfung und Bevölkerung wenn möglich aufteilen. Dies setzt voraus,

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

:

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. 
    } 
} 
+0

Ich mag das. Ich hatte diese Strategie bereits mit einer * AutoMapper * -basierten Populationsmethode als Übergangslösung implementiert. – ProfK

2

Sie Reflexion und Generika können (macht dies eine billige, Beispiel home-grown, dass kopiert alle Felder, ist es durchaus ein paar Annahmen der Kürze halber) dass der Typ einen parameterlosen Standardkonstruktor hat, aber Sie bekommen die Idee.

Alternativ, wenn die Leistung ein Problem ist, könnten Sie etwas wie einen Code-Generator erstellen, der den Zuweisungscode mithilfe von Teilklassen codiert.

+0

Das macht 'AutoMapper'. – Aliostad

+0

@Aliostad Wusste das nicht, benutzte nie AutoMapper. Ich habe das geschrieben, als du deine Antwort gepostet hast. Persönlich für etwas so kleines würde ich mir selbst einrollen, um eine Abhängigkeit zu vermeiden. –

+0

@Aliostad Nun, in diesem Fall könnte ich den Code direkt aus Auto Mapper herausheben, wenn er nicht von anderen internen Dingen abhängig ist. Aber ich würde immer noch die Abhängigkeit von einem ORM-Framework für etwas so einfaches wie Kopierkonstruktoren vermeiden. –