Reputation: 4969
I'm a little stumped on how to pass in a type argument to a Method, from a parameter.
public class MyNamespaceXmlFormatter : XmlMediaTypeFormatter
{
public override Task WriteToStreamAsync(Type type, object value,
Stream writeStream, HttpContent content,
TransportContext transportContext, System.Threading.CancellationToken cancellationToken)
{
XElement xmloutput = XElementSerialiser.ToXElement<type>(value);
...........
I've tried the following, but these fail as well;
XElement xmloutput = XElementSerialiser.ToXElement<(T)type>(value);
XElement xmloutput = XElementSerialiser.ToXElement<typeof(type)>(value);
Obviously this compiles, but makes little sense;
XElement xmloutput = XElementSerialiser.ToXElement<Type>(value);
Upvotes: 3
Views: 993
Reputation: 80765
Generic instantiation (i.e. adding <T>
to signature) is a compile-time construct, while Type
object exists at runtime.
It would be preferable, as D Stanley suggested, to make the whole method generic and not pass a Type
object at all.
However, if you're unable to do that, you can make yourself a generic factory with non-generic interface, and create instances of it dynamically. Like so:
interface IFactory {
XElement ToXElement( object value );
}
class Factory<T> : IFactory {
public XElement ToXElement( object value ) {
return XElementSerialiser.ToXElement<T>( value );
}
}
public override Task WriteToStreamAsync( Type type, object value,
Stream writeStream, HttpContent content,
TransportContext transportContext, System.Threading.CancellationToken cancellationToken) {
var factory = Activator.CreateInstance( typeof( Factory<> ).MakeGenericType( type ) ) as IFactory;
return factory.ToXElement( value );
}
For performance reasons, you might also want to cache the factory
instance.
UPDATE: made a blog post out of it.
Upvotes: 7
Reputation: 2306
I agree with D Stanley's answer but in case you want to have the compiler infer the type of the object to be serialized for you so you don't have to specify it each time you use the method use this:
public override Task WriteToStreamAsync<T>(T value,
Stream writeStream, HttpContent content,
TransportContext transportContext, System.Threading.CancellationToken cancellationToken)
{
XElement xmloutput = XElementSerialiser.ToXElement<T>(value);
Upvotes: 0
Reputation: 152616
You could do it using generics, but could you make WriteToStreamAsync
generic instead?
public override Task WriteToStreamAsync<T>(object value,
Stream writeStream, HttpContent content,
TransportContext transportContext, System.Threading.CancellationToken cancellationToken)
{
XElement xmloutput = XElementSerialiser.ToXElement<T>(value);
Upvotes: 4