2010-02-18 20 views
16

Estoy usando interfaces en este caso principalmente como un controlador para una instancia inmutable de un objeto. El problema es que las interfaces anidadas en C# no están permitidas. Aquí está el código:Alternativas a las interfaces anidadas (no es posible en C#)

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

Estoy buscando una alternativa, nadie tendría una solución?

+1

¿Hay algún motivo en particular por el que desee 'anotar ICountryInfo''? – AakashM

+2

Sí, la aplicación contiene más de 100 clases con muchas clases anidadas que llevan los mismos nombres. Es mucho más limpio si conservo esa configuración. En cuanto al uso de interfaces, es una forma de obtener sus contrapartes inmutables. Una vez que los objetos han sido instanciados, la aplicación principal trata principalmente con sus interfaces correspondientes usando el patrón de inyección de dependencia. – ericdes

Respuesta

12

VB.NET permite esto. Por lo tanto, puede crear un conjunto de VB.NET sólo con las definiciones de interfaz que usted necesita:

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 

En cuanto a la implementación, C# no es compatible con los tipos de retorno covariantes, por lo que debe declararse su clase como esta:

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

Esto funciona muy bien, no hay necesidad de nido:

public interface ICountry 
{ 
    ICountryInfo Info { get; } 
} 

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

Sí, pero ... esto derrota las razones por las que creé una clase anidada. ICountryInfo no debe tener un significado en ningún otro lugar que no sea dentro de ICountry. – ericdes

+8

Estoy de acuerdo con @ericdes. Esta es una situación en la que C# falla. –

2

Si ICountryInfo no tiene razón de existir fuera ICountry, entonces ¿por qué no le acaba de poner las propiedades de ICountryInfo en ICountry y descartar la idea de interfaces anidadas?

Una interfaz que no tiene un significado propio sin otra interfaz no tiene sentido para mí, ya que una interfaz en sí misma es inútil si no es implementada por una clase.

+0

+1 Estoy totalmente de acuerdo. Parece que no es necesario tener un ICountryInfo en este ejemplo. – Ian

+0

Bueno, acabo de extraer el código de ejemplo de una aplicación que contiene más de 100 clases con muchas clases anidadas que llevan los mismos nombres. Es mucho más limpio si conservo esa configuración con clases anidadas. En cuanto al uso de interfaces, es una forma de obtener sus contrapartes inmutables. Una vez que los objetos han sido instanciados, la aplicación principal trata principalmente con sus interfaces correspondientes usando el patrón de inyección de dependencia. No quiero modificar la estructura de anidamiento de manera que resulte en un código poco práctico. – ericdes

+4

Aunque estoy de acuerdo en que el ejemplo dado no tiene sentido y estaría mejor expresado como una sola interfaz, no significa que la idea no sea válida.Si, por ejemplo, la interfaz ICountry tuviera una colección de objetos ICountryInfo en lugar de solo uno, obviamente no funcionaría aplanarlo en una sola interfaz. ;) – CptRobby

2

Si el objetivo final es usar esto con la inyección de dependencia, ¿qué hay de malo al inyectarlos entre sí en lugar de anidar?

public interface ICountry 
{ 
    ICountryInfo Info { get; } 
} 

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

e implementar como:

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

Luego, una vez configuradas las fijaciones para ICountry & ICountryInfo, CountryInfo inyectará al país cada vez que se inyecta País.

A continuación, puede restringir el enlace, si lo desea, solo para inyectar CountryInfo en el país y en ningún otro lugar. Ejemplo en Ninject:

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