ericpap
ericpap

Reputation: 2937

Unknown types error over WCF service

I'm trying to use this method on WCF client:

public interface IOhmioService
{        
  [OperationContract]
  IEnumerable<Enumerador> GetEnumerador(Type type);       
}

public class OhmioService : IOhmioService
{
  public IEnumerable<Enumerador> GetEnumerador(Type type)
  {
     var _obj = (IEnumerador)Activator.CreateInstance(type);
     return _obj.Enumerar();  
  }
}

and Implemented like this:

public IEnumerable<Enumerador> GetEnumerador(Type type)
    {
        dynamic _obj = Activator.CreateInstance(type);
        return (IEnumerable<Enumerador>)_obj.Enumerar();
    }      

And it gives me error because of unknown types, but i can't understand why. The return type is known by server and client.I'm only trying to tell from client wich kind of object to create. I'm sure that if I pass the Type parameter as a string for instance and use a select case it will work without problems. Is there another way to do generic methods on WCF service? Thanks!

UPDATE

This is the error i get:

Type 'System.RuntimeType' wasn't spected with the contract name RuntimeType:http://schemas.datacontract.org/2004/07/System'. Trye to use DataContractResolver or add the unknown types staticaly to the list of known types (for instance, using the attribute KnownTypeAttribute or adding them to the list of known types to pass to DataContractSerializer)

Upvotes: 1

Views: 1150

Answers (1)

jnovo
jnovo

Reputation: 5769

Generics are not supported by WCF.

That being said, I assume you are passing sub-classes of Type to GetEnumerador. The problem lies in although your service knows about parameters of type Type and thus, implicitly creates a DataContract for it, it does not know about any other class. This makes serialization fail.

In order to fix it you need to make sub-classes explicit. You have several options

  • Customize the serialization by implementing a DataContractResolver
  • Use ServiceKnownTypes to annotate your contract which gives two options:
    1. Statically declare the sub-classes by using several ServiceKnownTypes annotations, one for each sub-class
    2. Specify a method that will be called dynamically to obtain the types

EDIT 1: if you are sure you are trying to serialize a Type object, take a look at this other question which shows solution to common problems.

EDIT 2 (after OP's update):

The error indicates that you are passing a System.RuntimeType object to GetEnumerador. Actually, given that System.Type is an abstract, GetEnumerador will always receive a sub-class of it.

As I said before, WCF only knows about Type which is what you specified in the contract and thus, it yields and error because it does not know how to serialize System.RuntimeType. The options I enumerated in the first place still apply. For instance, you can try this:

[ServiceKnownType(typeof(System.RuntimeType))]
public interface IOhmioService
{        
  [OperationContract]
  IEnumerable<Enumerador> GetEnumerador(Type type);       
}

Alternative if you are sure that GetEnumerador will always receive a System.RuntimeType you may do:

public interface IOhmioService
{        
  [OperationContract]
  IEnumerable<Enumerador> GetEnumerador(RuntimeType type);       
}

All in all, I would advise against serializing Type but if for some reason you feel like you must, take a look at the linked question.

Upvotes: 4

Related Questions