简体   繁体   中英

How to access values of a concrete interface implementation, when using the interface as a generic parameter to a method

I am trying to implement some generic models for a project, where I need each model to hold a value type of ICountryInformation. This interface will have different values depending on which country is implemented.

However, what I struggle with is how to actually use this in the right way. For instance, given a method:

DoSomething(ICountryInformation info) 
{
}

Say I have parsed a concrete implementation of ICountryInformation called GermanyInformation then I want to be able to fetch the information in relation to that concrete instance of ICountryInformation within my DoSomething() method.

But I can't seem to figure out how I can work around the fact that ICountryInformation do not have the concrete values of the GermanyInformation class which implements it.

How can I access the values of GermanyInformation, when it is parsed as an ICountryInformation beside actually having to cast it to a value inside the method? Is it even possible?

It's not the task of DoSomething to get the information. You must pass it as parameter when calling it

DoSomeThing(new GermanyInformation());

It makes sense to implement this information as singleton.

public class GermanyInformation : ICountryInformation
{
    public static readonly GermanyInformation Instance = new GermanyInformation();

    // Hide the constructor
    private GermanyInformation()
    {
    }

    ...
}

Then call it with

DoSomeThing(GermanyInformation.Instance);

If you want DoSomeThing to always use the German information, remove the parameter

DoSomething() 
{
    ICountryInformation info = GermanyInformation.Instance;
}

Another approach is to use a generic method or a method using a type parameter of an enclosing generic class (without the singleton implementation here)

void DoSomething<T>() where T : ICountryInformation, new()
{
    ICountryInformation info = new T();
}

call it with

DoSomething<GermanyInformation>();

or with a generic class

public class CountryService<T> where T : ICountryInformation, new()
{
    void DoSomething()
    {
        ICountryInformation info = new T();
    }
}

call it with

var service = new CountryService<GermanyInformation>();
service.DoSomething();

Note that you can't cast ICountryInformation to the desired country information. It references an object of a specific country information and you can't change that to another country.

The interface itself isn't an object. It is a contract a class can implement. You can then access the members of it in a neutral way through the interface, without having to know to which country it relates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM