2010-02-18 5 views
16

Ich benutze Interfaces in diesem Fall meist als Handle zu einer unveränderlichen Instanz eines Objekts. Das Problem besteht darin, dass verschachtelte Schnittstellen in C# nicht zulässig sind. Hier ist der Code:Alternativen zu verschachtelten Interfaces (in C# nicht möglich)

public interface ICountry 
{ 
    ICountryInfo Info { get; } 

    // Nested interface results in error message: 
    // Error 13 'ICountryInfo': interfaces cannot declare types 
    public interface ICountryInfo 
    { 
     int Population { get; } 
     string Note { get; } 
    } 
} 


public class Country : ICountry 
{ 
    CountryInfo Info { get; set; } 

    public class CountryInfo : ICountry.ICountryInfo 
    { 
     int Population { get; set; } 
     string Note { get; set; } 
     ..... 
    } 
    ..... 
} 

Ich suche eine Alternative, hätte jemand eine Lösung?

+1

Gibt es einen bestimmten Grund, warum Sie wollen, dass "ICountryInfo" verschachtelt wird? – AakashM

+2

Ja, die Anwendung enthält über 100 Klassen mit vielen verschachtelten Klassen, die die gleichen Namen tragen. Es ist viel sauberer, wenn ich diese Einstellung behalte. Wie für die Verwendung von Schnittstellen ist es eine Möglichkeit, ihre unveränderlichen Gegenstücke zu erhalten. Nachdem die Objekte instanziiert wurden, befasst sich die Hauptanwendung hauptsächlich mit ihren entsprechenden Schnittstellen, wobei das Abhängigkeitsinjektionsmuster verwendet wird. – ericdes

Antwort

12

VB.NET ermöglicht dies. So können Sie eine VB.NET Montage nur mit den Schnittstellendefinitionen erstellen, die Sie benötigen:

Public Interface ICountry 
    ReadOnly Property Info() As ICountryInfo 

    Public Interface ICountryInfo 
    ReadOnly Property Population() As Integer 
    ReadOnly Property Note() As String 
    End Interface 
End Interface 

Wie für die Implementierung, C# nicht kovarianten Rückgabetypen nicht unterstützt, so dass Sie Ihre Klasse wie folgt erklären muss:

public class Country : ICountry { 
    // this property cannot be declared as CountryInfo 
    public ICountry.ICountryInfo Info { get; set; } 

    public class CountryInfo : ICountry.ICountryInfo { 
    public string Note { get; set; } 
    public int Population { get; set; } 
    } 
} 
2

Das funktioniert ganz gut, keine Notwendigkeit, Nest:

public interface ICountry 
{ 
    ICountryInfo Info { get; } 
} 

public interface ICountryInfo 
{ 
    int Population { get; } 
    string Note { get; } 
} 
+3

Ja, aber ... das vereitelt die Gründe, warum ich eine verschachtelte Klasse erstellt habe. ICountryInfo sollte an keiner anderen Stelle als innerhalb von ICountry eine Bedeutung haben. – ericdes

+8

Ich stimme @ericdes zu. Dies ist eine Situation, in der C# fehlschlägt. –

2

Wenn ICountryInfo keinen Grund außerhalb iCountry zu existieren hat, warum sollte dann nicht nur Sie die Eigenschaften von ICountryInfo in iCountry setzen und die Idee entlassen von verschachtelten Schnittstellen?

Eine Schnittstelle, die ohne eine andere Schnittstelle keine eigene Bedeutung hat, macht für mich keinen Sinn, da eine Schnittstelle an sich nutzlos ist, wenn sie nicht von einer Klasse implementiert wird.

+0

+1 würde ich völlig zustimmen. Es scheint in diesem Beispiel keine ICountryInfo zu geben. – Ian

+0

Nun, ich habe den Beispielcode nur aus einer Anwendung extrahiert, die über 100 Klassen mit vielen verschachtelten Klassen mit den gleichen Namen enthält. Es ist viel sauberer, wenn ich dieses Setup mit verschachtelten Klassen behalte. Wie für die Verwendung von Schnittstellen ist es eine Möglichkeit, ihre unveränderlichen Gegenstücke zu erhalten. Nachdem die Objekte instanziiert wurden, befasst sich die Hauptanwendung hauptsächlich mit ihren entsprechenden Schnittstellen, wobei das Abhängigkeitsinjektionsmuster verwendet wird. Ich möchte die Verschachtelungsstruktur nicht so ändern, dass unpraktischer Code entsteht. – ericdes

+4

Während ich zustimme, dass das gegebene Beispiel nicht wirklich Sinn macht und besser als eine einzige Schnittstelle ausgedrückt werden würde, bedeutet das nicht, dass die Idee ungültig ist.Wenn zum Beispiel die ICountry-Schnittstelle eine Sammlung von ICountryInfo-Objekten anstelle von nur einer hätte, würde es offensichtlich nicht funktionieren, sie in einer einzigen Schnittstelle zu verflachen. ;) – CptRobby

2

Wenn das Endziel ist, dies mit Abhängigkeitsinjektion zu verwenden, was ist falsch daran, sie ineinander zu injizieren statt zu verschachteln?

public interface ICountry 
{ 
    ICountryInfo Info { get; } 
} 

public interface ICountryInfo 
{ 
    int Population { get; set; } 
    string Note { get; set; } 
} 

und implementieren als:

public class Country : ICountry 
{ 
    private readonly ICountryInfo _countryInfo; 

    public Country(ICountryInfo countryInfo) 
    { 
     _countryInfo = countryInfo; 
    } 

    public ICountryInfo Info 
    { 
     get { return _countryInfo; } 
    } 
} 

public class CountryInfo : ICountryInfo 
{ 
    public int Population { get; set; } 
    public string Note { get; set;} 
} 

Dann, wenn Sie Ihre Bindungen für iCountry & ICountryInfo einrichten, wird in Country Land injizieren, wenn Land injiziert wird.

Sie könnten dann die Bindung einschränken, wenn Sie möchten, nur CountryInfo in Land und nirgendwo sonst zu injizieren. Beispiel in Ninject:

Bind<ICountry>().To<Country>(); 
Bind<ICountryInfo>().To<CountryInfo>().WhenInjectedInto<Country>();