Inferring type parameter in method

Viewed 151

I have a hierarchy of classes in my C# library representing domain entities, all eventually descending from a root abstract class named DomainEntity. Some examples are Package or Customer. I employ Create() factory methods in each class to create instances. I also have a generic processor class Processor<T> where T: DomainEntity. This processor class also uses a factory method to be instantiated and performs business logic that depends on the specific class, hence its type parameter. Using this library, I can for example write code like this:

var pkg = Package.Create(/* various arguments */);
var pro = Processor<Package>.Create(pkg);
pro.DoStuff();

So far so good. Now I would like to write a method in DomainEntity that returns a processor for any particular domain entity. Something like this:

public Processor<T> CreateProcessor<T>()
    where T: DomainEntity
{
    var pro = Processor<T>.Create((T)this);
    return pro;
}

This method can be used like this:

var pkg = Package.Create(/* various arguments */);
var pro = pkg.CreateProcessor<Package>();
pro.DoStuff();

This works fine, but I find the Package reference in the call to CreateProcessor() a bit redundant, as I am calling the method on an instance of Package and therefore there is no ambiguity as to which class the type parameter should refer. However, this will not compile:

var pkg = new Package(/* various arguments */);
var pro = pkg.CreateProcessor(); //<-- this does not compile.
pro.DoStuff();

My question is:

Is there an alternative way to write the CreateProcessor() method so that the type parameter is inferred by the compiler from the object it is being called on?

I can provide a complete working Visual Studio project on demand.

2 Answers

You just need to create a generic extension method:

public static class EntityExtensions
{
    public static Processor<T> CreateProcessor<T>(this T entity)
        where T : DomainEntity
        => new Processor<T>(entity);
}

That should allow you to use type inference just fine:

var package = new Package();
var processor = package.CreateProcessor();

That second line is equivalent to:

var processor = EntityExtensions.CreateProcessor<Package>(package);

What about using a factory method:

static Processor<T> CreateProcessor<T>() {
    var package = new Package();
    T pro = package.CreateProcessor<T>();
    return pro;
}

// Usage
CreateProcessor<Package>().DoStuff();

I tried to find a way to use the type-specialization quiet a while ago and figured out that this does not work in C#. You can check this blog post

Related