guylegend
guylegend

Reputation: 85

Is it possible to have strongly typed parameter constraints in a constructor of a generic class?

I would like to define a generic class in C#:

public class MyService<TModel>
{
    public MyService(/*What to declare here?*/)
    {
    }
}

such that I can instantiate it like the following:

var service = new MyService<SomeModel>(m => m.SomeField);

where SomeField is restricted to be a field of SomeModel. Is this possible?

I know I can declare something similar for a method within the class but can't quite figure out how this can be done for constructors. For example, I can declare the following in MyService:

    public void SomeMethod<TMember>(Expression<Func<TModel, TMember>> member)
    {
    }

and be able to invoke it like this:

var service = new MyService<SomeModel>();
service.SomeMethod(m => m.SomeField);

and the compiler would complain if SomeField wasn't actually a field of SomeModel.

Upvotes: 1

Views: 240

Answers (2)

Enigmativity
Enigmativity

Reputation: 117010

You can do this:

public class MyService<TModel>
{
    public static MyService<TModel> Create<TMember>(Func<TModel, TMember> member)
    {
        return new MyServiceImpl<TMember>(member);
    }

    private class MyServiceImpl<TMember> : MyService<TModel>
    {
        private Func<TModel, TMember> member;
        public MyServiceImpl(Func<TModel, TMember> member)
        {
            this.member = member;
        }
    }
}

So now I can do this:

MyService<Foo> service = MyService<Foo>.Create(m => m.Name);

Note, that I don't need to specify the type of the member.

Here's my class Foo:

public class Foo
{
    public string Name;
}

Upvotes: 3

Scott Chamberlain
Scott Chamberlain

Reputation: 127543

You must put both TModel and TMember both in the <> in the constructor.

public class MyService<TModel, TMember>
{
    public MyService(Expression<Func<TModel, TMember>> member)
    {
    }
}

You can't create a constructor that uses extra generic parameters that are not part of the class like you can with a method.

Upvotes: 1

Related Questions