Reputation: 85
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
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
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