Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize an interface that has type aguments of the type of another Interface

Tags:

c#

ive run into a problem - these is my class structure

public interface IModel{}

public interface IGenericMapper<T> where T : IModel {...}

public class ActualModel:IModel {...}

public class ActualMapper: IGenericMapper<ActualModel> {...}

My actual code to initialse the mapper is:

IGenericMapper<IModel> mapper;
mapper= new ActualMapper();

It does not compile. I get the error

Cannot implicitly convert type 'ActualMapper' to 'IGenericMapper'. An explicit conversion exists (are you missing a cast?)

When I do cast it using

mapper= new ActualMapper() as IGenericMapper<IModel>;

the mapper does not get initialized properly (it comes back as NULL)

What am I missing - since ActualMapper() implements IGeneric Mapper and its type impliments `IModel' why can it not initialize mapper.

Is there another way to structure this so achieve what I need?

Thank you so much

Note the solution people have proposed gives me other compilation errors as the mapping Interface has the following members

T GetModel(busO bBusinessObject);
busO  SetBusObject(T source, busO  target);

apparently you cant have the generic type as an input parameter when its declared at "out"

like image 329
gfdoomchicken Avatar asked Aug 16 '13 13:08

gfdoomchicken


People also ask

How do you initialize an interface property?

Use a type assertion to initialize a typed, empty object using an interface in TypeScript, e.g. const emp1 = {} as MyInterface . You can access or set any properties on the object, as long as they exist on the interface and are compatible with the corresponding types.

Can we initialize interface in TypeScript?

We cannot instantiate the interface, but it can be referenced by the class object that implements it. The TypeScript compiler uses interface for type-checking (also known as "duck typing" or "structural subtyping") whether the object has a specific structure or not.

How do you pass an interface as a parameter TypeScript?

An interface type cannot be passed as a parameter. When running TypeScript code, you are really compiling it down to JavaScript and then running the JavaScript. An interface is a TypeScript compile-time construct, so at runtime, there is no such thing as an interface type to call functions on or inspect properties of.

Can you create objects of an interface type?

Like abstract classes, interfaces cannot be used to create objects (in the example above, it is not possible to create an "Animal" object in the MyMainClass) Interface methods do not have a body - the body is provided by the "implement" class. On implementation of an interface, you must override all of its methods.


2 Answers

Pretty sure you're moving into the realm of covarience here with the Generic change;

try this:

public interface IModel{}
public interface IGenericMapper< out T> where T : IModel{}
public class ActualModel : IModel{}
public class ActualMapper : IGenericMapper<ActualModel>   {}

and then:

IGenericMapper<IModel> blah = new ActualMapper();

with out the 'out T' the best you can do is:

IGenericMapper<ActualModel> blah = new ActualMapper();

This is a rabbit hole, so be careful especially if you ever try to mix the two :)

http://msdn.microsoft.com/en-us/library/ee207183.aspx

[Edit]

If you want to be able to downcast the generic T, then it has to be out and you cannot use it as an input. You can, however, move some of it to real time in your implementation; i.e. to a check to see if you can cast it to a model type.

interface IGenericMapper<out TModel, in TKeyOrIdent> 

TModel GetModel(TKeyOrIdent bBusinessObject);
void SetModel(object model, TKeyOrIdent target);
like image 189
Meirion Hughes Avatar answered Sep 27 '22 20:09

Meirion Hughes


you have to define

IGenericMapper<out T>

to support your scenario, but this applies other limitations.

Simply IGenericMapper<IModel> != IGenericMapper<ActualModel> even if ActualModel : IModel

In most scenarios it makes sense to have a base interface that isn't a generic. See IList<T> for example, it implements IList.

You can then choose on implementation to explicitly implement interface members. See List<T>.GetEnumerator() : IEnumerable

Do not use generics under the assumption that you can eliminate casting everywhere. I've tried it C# simply doesn't have the required features for this.

I would suggest an IGenericMapper interface as base interface for IGenericMapper<T> then do your generic code on IGenericMapper and finally (and at that point you already have the type) cast it back to the specific type.

like image 22
LunicLynx Avatar answered Sep 27 '22 20:09

LunicLynx