Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplify generic type inferring

Tags:

c#

.net

generics

I'm writing a generic code that should handle situations when data is loaded from multiple sources. I have a method with following signature:

public static TResult LoadFromAnySource<TContract, TSection, TResult>
    (this TSection section, 
          string serviceBaseUri, 
          string nodeName)
    where TSection : ConfigurationSection
    where TResult : IDatabaseConfigurable<TContract, TSection>, new() 
    where TContract : new()

But it's an overkill: when I pass TResult, I already know what TContract and TSection exactly are. In my example:

public interface ISourceObserverConfiguration 
    : IDatabaseConfigurable<SourceObserverContract, SourceObserverSection>

But I have to write following:

sourceObserverSection.LoadFromAnySource<SourceObserverContract, 
                                        SourceObserverSection, 
                                        SourceObserverConfiguration>
    (_registrationServiceConfiguration.ServiceBaseUri, nodeName);

You can see that I have to specify pair <SourceObserverContract, SourceObserverSection> twice, it's a violation of DRY principe. So I'd like to write something like:

sourceObserverSection.LoadFromAnySource<SourceObserverConfiguration>
   (_registrationServiceConfiguration.ServiceBaseUri, nodeName);

and make SourceObserverContract and SourceObserverSection inferred from interface.

Is it possible in C# or I should specify it everywhere manually?

IDatabaseConfigurable looks like:

public interface IDatabaseConfigurable<in TContract, in TSection> 
    where TContract : ConfigContract
    where TSection : ConfigurationSection
{
    string RemoteName { get; }

    void LoadFromContract(TContract contract);

    void LoadFromSection(TSection section);
}

Then extension just calls these two methods based on some logic. I must specify types becuase I need to access properties of each specific realisation, so I need a covariance.

like image 229
Alex Zhukovskiy Avatar asked May 06 '16 12:05

Alex Zhukovskiy


1 Answers

No you can't. Type inference does not take into account the return type of a method. TResultmight contain all the information needed but type inference will not use it.

You'll need to make TContract part of the method's signature so that the type can be inferred. TResult is redundant, there is no need for it to be generic, simply use IDataBaseConfigurable<TContract, TSection> as the method's return type.

like image 119
InBetween Avatar answered Oct 16 '22 19:10

InBetween