2016-09-07 2 views
-2

Ich habe eine Klasse namens Property, die einen Wert speichert und ein Ereignis auslöst, wenn sich der Wert ändert. Es gibt eine andere Klasse namens Observable, die ein Wörterbuch mit Eigenschaften enthalten soll, und ich habe ein Beispiel unten. Wie kann ich den Typ einer im Wörterbuch gespeicherten Eigenschaft abrufen, damit ich das Objekt ändern kann?C# Casting-Objekt zu Klasse mit Typ Argument

Objektklasse:

public class Property<T> 
{ 
    public T Value { get; set; } 
} 

beobachtbare Klasse:

public class Observable 
{ 
    public readonly Dictionary<string, object> 
       Properties = new Dictionary<string, object>(); 

    public Property<T> Get<T>(string name) 
    { 
     object obj; 
     Properties.TryGetValue(name, out obj); 
     return (Property<T>) obj; 
    } 
} 

EDIT: Dies ist der Fehler, den ich immer bin - Unbehandelte Ausnahme: System.InvalidCastException: Kann nicht werfen Aufgabe Geben Sie 'System.String' ein, um 'ConsoleApplication.Property`1 [System.String]' einzugeben.

Auch, wenn ich die Get-Funktion loswerden und sie durch etwas ersetzen könnte, das den Typ nicht kennt, wäre das viel besser.

Aktualisieren: Gibt es eine Möglichkeit, den Typ durch Hashing des Namens mit einem Typ zu erhalten?

+0

http://stackoverflow.com/questions/2399710/how-to-get-type-of-tkey-and-tvalue-given-a-dictionarytkey-tvalue-type –

+0

Haben Sie davon ausgehen wollen, dass'Erhalte (...) 'Wird es gelingen? Was stimmt nicht mit dem von dir bereitgestellten Code? –

+0

das ist nicht das, was ich frage. Ich möchte nicht den Typ des Wörterbuchwerts erhalten, sondern den Typ des Wertes in einer Eigenschaft. –

Antwort

2

EDIT (für aktualisiert post):

Gibt es einen Weg, um die Art zu erhalten, indem Sie den Namen mit einem Typ-Hashing?

Ist etwas wie das, was Sie anstreben? dotnetfiddle link

public interface IProperty 
{ 
    object Value { get; } 
    Type TypeOfValue { get; } 
} 

public class Property : IProperty 
{ 
    public object Value { get; set; } 
    public Type TypeOfValue { get; set; } 
    public override string ToString() { return TypeOfValue.FullName + ": " + Value; } 
} 

public class Observable 
{ 
    public readonly Dictionary<string, Property> 
     Properties = new Dictionary<string, Property>(); 

    // use interface so consumer of your property can't mess with the 
    // type or value stored in your dictionary within Observable 
    public IProperty Get(string name) 
    { 
     Property obj; 
     if (Properties.TryGetValue(name, out obj)){ 
      return obj; 
     } 

     // throw something which makes more sense to you 
     throw new ArgumentException(name + " does not exist in the dictionary"); 
    } 

    // sample of how you'd store these properties 
    public void Set(string name, object val) 
    { 
     if (Properties.ContainsKey(name)){ 
      Properties[name].Value = val; 
      Properties[name].TypeOfValue = val.GetType(); 
     } else { 
      Properties[name] = new Property { 
       Value = val, 
       TypeOfValue = val.GetType() 
      }; 
     } 
    } 
} 

ORIGINAL ANTWORT:

Es ist möglich, dass Sie versehentlich ein string in Ihr Wörterbuch innerhalb von Observable anstelle eines Property<string> Einfügen, und wenn ja das Problem nicht in dem Code, den Sie‘ gepostet und stattdessen, wo immer Sie eine string anstelle einer Property<string> einfügen.

Zwei Lösungen, wenn Sie die ungültige Cast-Ausnahme nicht mögen.

Lösung 1: passen Sie die Fehler an, die Ihre Funktion verursacht.

Wenn Sie die Signatur von Get<T>(...) behalten möchten, würde ich einige Fehlerbehandlung empfehlen. Der Fehler, den Sie sehen, liegt darin, dass die Eigenschaft in Ihrem Wörterbuch vom Typ string ist, nicht vom Typ Property<string>. Der folgende Code gibt Ihnen etwas für die weitere Fehlerbehandlung.

public class Observable 
{ 
    public readonly Dictionary<string, object> 
     Properties = new Dictionary<string, object>(); 

    public Property<T> Get<T>(string name) 
    { 
     object obj; 
     if (Properties.TryGetValue(name, out obj)){ 
      try { 
       return (Property<T>) obj; 
      } catch(InvalidCastException){ 
       // throw something which makes more sense to you 
       throw new ArgumentException("Could not cast the given object to the desired type"); 
      } 
     } 

     // throw something which makes more sense to you 
     throw new ArgumentException(name + " does not exist in the dictionary"); 
    } 
} 

Lösung 2: Rückkehr ein allgemeines object

public class Observable 
{ 
    public readonly Dictionary<string, object> 
     Properties = new Dictionary<string, object>(); 

    public object Get(string name) 
    { 
     object obj; 
     if (Properties.TryGetValue(name, out obj)){ 
      return obj; 
     } 

     // or do whatever you want when the given key doesn't exist. 
     return null; 
    } 
} 
0

Indexer Ihr Problem ohne zusätzliche Konstrukte lösen kann. Schau mal wenn du bist Ich bin mir nicht sicher, ob ich dich klar habe, aber ich werde versuchen zu helfen) Für mich kann die Frage wie folgt umformuliert werden. Ist es möglich, den spezifischsten Typ des Upcast-Typs zu bestimmen?

Hier ist ein Code, den Sie

public class Employee 
{ 
    public int salary { get; set; } 

} 

public class Manager : Employee 
{ 

} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Manager man = new Manager(); 
     System.Object emp = (object) man; 
     Console.WriteLine(emp.GetType()); 
    } 
} 

Der Ausgang des Console.WriteLine Betrieb ist „Project_Name“ .manager helfen können, so dass Sie, welche Art sehen ursprünglich im Speicher zugewiesen wurde. nicht vertraut mit ihnen.

Verwandte Themen