2013-08-12 3 views
5

Ich habe eine große Sammlung von automatisch generierten Objekten. Obwohl sie alle aus verschiedenen, nicht verwandten Klassen bestehen, teilen sich alle Objekte einige grundlegende Eigenschaften (Name, ID usw.). Ich kontrolliere nicht die Generierung dieser Objekte, daher kann ich leider nicht den idealen Ansatz zur Implementierung einer Schnittstelle wählen. Ich möchte eine Methode erstellen, in der ich ein beliebiges dieser Objekte übergebe und etwas unter Verwendung dieser gemeinsamen Eigenschaften tue.Methode zum Behandeln von Objekten mit gemeinsamen Eigenschaften, aber unterschiedlichen Objekttypen

Die allgemeine Idee wäre so etwas wie:

someObj a = new someObj(); 
a.name = "sara"; 
diffObj b = new diffObj(); 
b.name = "joe"; 
string phrase = string.Format("I am with {0} and {1}", 
    getName(a), getName(b)); 

private string getName(object anyObjWithName) 
{ 
    return anyObjWithName.name; 
} 

aber natürlich funktioniert das nicht.

Ich dachte, eine generische Methode könnte die Antwort halten, aber die einzige Möglichkeit, wie ich es mit dem aktuellen Typ aufrufen kann, ist genericMethod.Invoke, die immer noch das gleiche Problem der nicht in der Lage, die Eigenschaften des übergebenen Objekts zu lösen in der Methode. Dies ist ungleich Calling generic method with a type argument known only at execution time oder How to call generic method with a given Type object?, wobei nur der Typ oder Eigenschaften des Typs in der Methode verwendet werden, im Gegensatz zu Eigenschaften des Objekts.

Ich bin mir bewusst, dass dies (sehr) anfällig für Fehler wäre, aber ich kann garantieren, dass alle angetroffenen Objekte die gemeinsamen Eigenschaften manipuliert haben.

+5

Verwenden Sie eine Schnittstelle? – Michael

+0

Versuchen Sie entweder, eine Schnittstelle zu deklarieren, um die Objekte für allgemeine Eigenschaften in Beziehung zu setzen, oder verwenden Sie Reflektion. – Nayan

+1

http://msdn.microsoft.com/en-us/library/64syzecx.aspx – Crisfole

Antwort

9

Ich kann garantieren, dass alle die gemeinsamen Eigenschaften angetroffen Objekte

manipuliert werden muss Wenn das der Fall ist, können Sie dynamic:

private string getName(dynamic anyObjWithName) 
{ 
    return anyObjWithName.name; 
} 

Beachten Sie, dass jedes Objekt verwenden, hat keine name Eigenschaft wird nicht bis zur Laufzeit fehlschlagen.

Wenn Sie ein wenig Sicherheit hinzuzufügen, können Sie die RuntimeBinderException zu fangen, die ausgelöst wird, wenn die Eigenschaft nicht existiert:

private string getName(dynamic anyObjWithName) 
{ 
    try { 
     return anyObjWithName.name; 
    } 
    catch(RuntimeBinderException) { 
     return "{unknown}"; 
    } 
} 
+0

Cool, ich habe diese Lösung nie gesehen ... – ganders

+3

Für meine $ .02 glaube ich nicht, dass das OP in der Lage ist, den "dynamischen" Pfad zu beginnen. Die Straße ist voller Gefahren und diese Antwort ist überhaupt nicht pädagogisch. –

+1

Ich wusste, dass ich etwas Schmerzen hatte. Da ich keine Schnittstelle implementieren kann, bin ich mir nicht sicher, ob es eine andere Möglichkeit gibt. – MaxPRafferty

0

Sie sind eine Rube Goldberg Vorrichtung zu schaffen. Sie sollten nur alle Ihre Datenobjektklassen implementieren eine einzige Schnittstelle, dann können Sie daran arbeiten. Viel einfacher und weniger fehleranfällig als mit Reflexionen zu spielen.

Die Tatsache, dass viele Objekte gemeinsame Eigenschaften haben, aber nicht die gleiche Herkunft haben, zumindest eine gemeinsame Schnittstelle, zeigt, dass mit Ihrem Design etwas nicht stimmt. Überlege es neu.

+2

Das ist wirklich, wo das Problem kommt - ich kontrolliere nicht die Generierung der Objekte. Mein Königreich für eine Schnittstelle! – MaxPRafferty

0

Mehrere Möglichkeiten, um dies zu erreichen, sind am einfachsten wahrscheinlich Schnittstelle zu schaffen und gemeinsame Methoden dort zu erklären, haben Sie Ihr Objekt, um es zu implementieren, dann ändern „getName“ Objekt-Interface-Methode nehmen

private string getName(IMyInterface anyObjWithName) 
{ 
    return anyObjWithName.name; 
} 
0

den richtigen Weg, dies zu tun eine Schnittstelle ist mit, wenn Sie die Typen besitzen, die Sie gerade arbeiten

public interface IEntity 
{ 
    int ID { get; set; } 
    string Name { get; set; } 
} 

public class TypeOne : IEntity 
{ 
    public int ID { get; set; } 
    public string Name { get; set } 

    public string BespokePropertyOne { get; set;} 
} 

public class TypeTwo : IEntity 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 

    public float BespokePropertyTwo { get; set; } 
} 

static void Main(string[] args) 
{ 
    List<IEntity> entities = new List<IEntity>(); 
    entities.Add(new TypeOne() { ID = 1, Name = "Bob", BespokePropertyOne = "blablabla" }); 
    entities.Add(new TypeTwo() { ID = 2, Name = "Alice", BespokePropertyTwo = 5.4f }); 

    foreach (IEntity entity in entities) 
    { 
     Console.WriteLine("ID: {0} Name: {1}", entity.ID, entity.Name); 
    } 
} 
+0

OP hat keine Möglichkeit Klassen zu steuern. Es ist in Frage gestellt. – nawfal

0

Diese Antwort vor der Bearbeitung auf die Frage geschrieben wurde besagt, dass Schnittstellen in diesem Fall nicht möglich waren. Vielleicht kann es jemandem helfen, der diese Frage liest.

Schnittstelle:

interface Iname 
{ 
    string Name { get; set; } 
} 

Verwenden:

class A : Iname 
{ 
    public string Name { get; set; } 
} 

class B : Iname 
{ 
    public string Name { get; set; } 
} 

Die Methode:

string GetName(Iname o) 
{ 
    return o.Name; 
} 

Verwendung:

A a = new A { Name = "First" }; 
B b = new B { Name = "Last" }; 
Text = GetName(a) + " " + GetName(b); 
+0

OP hat keine Möglichkeit, Klassen zu steuern. Es ist in Frage gestellt. – nawfal

2

Wenn Sie mit der von D Stanley erwähnten Dynamik nicht zufrieden sind, können Sie es mit FastMember versuchen.

Alles, was Sie wissen müssen, um damit zu beginnen, wird in den ersten beiden Codebeispielen gezeigt.

+0

Wow, ja, diese Bibliothek existiert buchstäblich, um genau dieses Problem zu lösen. Ich frage mich, wie es unter der Haube ohne Reflexion funktioniert ... – MaxPRafferty

+1

@MaxPRafferty: IIRC, es wird Reflexion nutzen, um die Mitglieder Informationen das erste Mal zu erhalten, schreiben gleichwertige Kompilierzeit IL, dann verwendet, dass kompilierten Code für den anschließenden Zugriff darauf Geben Sie/Mitglied ein. Dies ergibt eine Geschwindigkeit, die dem kompilierten Code im Vergleich zum häufigen Treffen der DLR oder der Reflexion näher kommt. –

Verwandte Themen