Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Generics: Can I constrain to a set of classes that don't implement an interface?

Tags:

c#

.net

generics

I have 3 classes that are essentially the same but don't implement an interface because they all come from different web services.

e.g.

  • Service1.Object1
  • Service2.Object1
  • Service3.Object1

They all have the same properties and I am writing some code to map them to each other using an intermediary object which implements my own interface IObject1

I've done this using generics

public static T[] CreateObject1<T>(IObject1[] properties)
  where T : class, new()
{
   //Check the type is allowed
   CheckObject1Types("CreateObject1<T>(IObject1[])", typeof(T));
   return CreateObjectArray<T>(properties);
}

private static void CheckObject1Types(string method, Type type)
{
  if (type == typeof(Service1.Object1)
  || type == typeof(Service2.Object1)
  || type == typeof(Service3.Object1)
  || type == typeof(Service1.Object1[])
  || type == typeof(Service2.Object1[])
  || type == typeof(Service3.Object1[]))
  {
     return;
  }

  throw new ArgumentException("Incorrect type passed to ServiceObjectFactory::" + method + ". Type:" + type.ToString());
}

My client code looks like:

//properties is an array of my intermediary objects
Object1[] props = ServiceObjectFactory.CreateObject1<Object1>(properties);

What I want to do is get rid of the CheckObject1Types method and use constraints instead so that I get a build error if the types aren't valid, because at the moment I can call this method with any type and the ArgumentException is thrown by the CheckObject1Types method.

So I'd like to do something like:

public static T[] CreateObject1<T>(IObject1[] properties)
  where T : class, new(), Service1.Object1|Service2.Object1|Service3.Object1
{
   return CreateObjectArray<T>(properties);
}

Any ideas?

Edit: I don't want to change the Reference.cs files for each webservice because all it takes is a team mate to update the web reference and BAM! broken code.

like image 482
Rob Stevenson-Leggett Avatar asked Oct 20 '08 15:10

Rob Stevenson-Leggett


1 Answers

Assuming the generated classes are partial, you can create an interface and then add another partial source file to make your generated classes implement the interface. Then you can constrain by interface as normal. No changes to the actual generated code required :)

like image 99
Jon Skeet Avatar answered Sep 29 '22 23:09

Jon Skeet