I have a simple class
public class Message<T>
{
public T Item { get; set; }
public Message(T item)
{
Item = item;
}
}
I want to create a base type BaseEvent
for another set of classes, having a method ToMessage
to convert to a message class like:
IConcreteEvent event = new ConcreteEvent(...);
Message<IConcreteEvent> = event.ToMessage();
Having the interface in the generic type of Message<T>
is important because this object will be sent via web service.
I did something like
public interface IBaseEvent<T>
{
Message<T> ToMessage();
}
public class BaseEvent<T> : IBaseEvent<T>
{
public Message<T> ToMessage()
{
return new Message<T>((T)this); //error!
}
}
public interface IConcreteEvent : IBaseEvent<IConcreteEvent>
{ }
public class ConcreteEvent : BaseEvent<IConcreteEvent>, IConcreteEvent
{ }
I get the error Cannot convert BaseEvent<T> to T
.
I tried to force this by doing
T value = (T)Convert.ChangeType(this, typeof(T));
return new Message<T>(value);
but I get the error Object must implement IConvertible
.
If I debug types I see that this
is of type ConcreteEvent
while typeof(T)
is IConcreteEvent
.
Why is the cast not working?
Finally found a solution but it took some time.
This solution is not safe : if the class ConcreteEvent
don't implement its interface IConcreteEvent
, you'll get a runtime InvalidCastException
with message Unable to cast object of type 'ConcreteEvent' to type 'IConcreteEvent'
I also added the constraint where T : IBaseEvent<T>
to the class BaseEvent<T>
to better check types.
The method ToMessage
can be implemented like
object value = this;
return new Message<T>((T)value);
Below a complete working example
void Main()
{
IConcreteEvent e = new ConcreteEvent();
Message<IConcreteEvent> msg = e.ToMessage();
}
public class Message<T>
{
public T Item { get; set; }
public Message(T item)
{
Item = item;
}
}
public interface IBaseEvent<T>
{
Message<T> ToMessage();
}
public class BaseEvent<T> : IBaseEvent<T>
where T : IBaseEvent<T>
{
public Message<T> ToMessage()
{
object value = this;
return new Message<T>((T)value);
}
}
public interface IConcreteEvent : IBaseEvent<IConcreteEvent>
{ }
public class ConcreteEvent : BaseEvent<IConcreteEvent>, IConcreteEvent
{ }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.