Tech Off Thread

14 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Casting generic interfaces

Back to Forum: Tech Off
  • User profile image
    PerfectPhase

    I was wondering if there is anyway to down cast a generic interface?

    What I whant to do is something like this, I have an interface like this

    interface MyInterface<T>
    {
       T GetValue ();
    }



    and in code I would like some generic code to do something like this:

    MyStringClass : MyInterface<string>


    MyStringClass sc = new MyStringClass () ;
    ...
    ...
    if (sc is MyInterface<object>)
    {
       MyInterface<object> dc = (MyInterface<object> )sc ;
       object o = dc.GetValue () ;
    }


    I'm pretty sure that I can't do this and it would be best to add a second non generic interface that does the cast for me.

    Any comments?

    Cheers,

    Stephen.


  • User profile image
    TypeSpafe

    In that specific instance, you should just have a non-generic base interface with an object version of the property:

    interface MyInterface
    {
       object GetValue ();
    }

    interface MyInterface<T> : MyInterface
    {
       T GetValue ();
    }

    Then you can

    MyStringClass : MyInterface<string>

    MyStringClass sc = new MyStringClass () ;
    ...
    ...
    MyInterface dc = sc as MyInterface;
    if (dc != null)
    {
       object o = dc.GetValue () ;
    }

    Note also the use of the as keyword to perform casting...

  • User profile image
    PerfectPhase

    Cheers, that's what I though, but you can but hope Smiley

  • User profile image
    Sven Groot

    In general, SomeClass<X> and SomeClass<Y> are not related, even if Y : X. So you cannot cast between them.

  • User profile image
    evildictait​or

    If you have to resort to reflection to solve a problem, it means that you are approaching the problem from the wrong direction.

    You should never ever ever ever ever ever ever use reflection. ever.

  • User profile image
    JChung2006

    It's possible using System.Reflection.
    // C# 3.0static class TypeUtil{    static public Type[] GetGenericArgumentsByInterface(this Type type,        string interfaceName, int arity)    {        Type genericInterface = type.GetInterfaces()            .Where(i => i.Name.Contains(string.Format("{0}`{1}", interfaceName, arity)))            .FirstOrDefault();        return (genericInterface != null) ? genericInterface.GetGenericArguments() : null;    }}// Sample code using extension methodstatic void Main(string[] args){    MyStringClass myString = new MyStringClass();    Type[] genericArguments = myString.GetType()        .GetGenericArgumentsByInterface("MyInterface", 1);    bool containsObject = genericArguments.Contains(typeof(object));}
    It's also possible to write a function like GetGenericArgumentsByInterface with this signature: IsGenericInterface(string interfaceName, param[] Type genericArguments) so your is MyInterface<object> expression could be written as IsGenericInterface("MyInterface", typeof(object)).

    You don't need C# 3.0 or LINQ to do this; it just makes writing the code to do this easier.

  • User profile image
    JChung2006

    I disagree, but I already knew that you don't like reflection.  I prefer dynamic languages so I like its flexibility when dealing with special requirements.  In this particular case, the OP is trying to work around an artifact of C#'s type system, which is that you can't work easily with generics until they're bound.

    By the way things are shaping up with strongly typed languages like F# offering the flexibility and functionality previously found only in dynamically typed languages and C# and VB.NET trying to incorporate some of the lessons learned from F# to offer the same, it would not hurt people to learn a few tricks from the dynamic language folks while enjoying the benefits of strong typing via type inference and better constructed type systems.

  • User profile image
    stevo_

    Avoiding reflection and saying it should never be used is a very bad assessment made in your mind.. while reflection is obviously slower, it isn't to a degree that makes it useless.. it just means.. don't use reflection to skip something that could be acheived with a little more work with regular interactions..

    Plus reflection is 'dynamics of dynamics' that lets you achieve a lot of 'cool' things.. I'm sure however that it will slowly be replaced in terms of functionality with more dynamics around the CLR (i.e., DLR)..

  • User profile image
    TypeSpafe

    evildictaitor wrote:
    If you have to resort to reflection to solve a problem, it means that you are approaching the problem from the wrong direction.

    You should never ever ever ever ever ever ever use reflection. ever.


    I'm creating a business object framework wherein the business objects provide string-indexed access to their properties. For example:

    class Person : BusinessObject<Person>
    {
        public string Forename { get; set; }
    }
    ...
    Person person = new Person();
    person["Forename"] = "Bob";

    This gives me flexible runtime access to the object properties so the end user of the application can achieve all manner of runtime goodness. How would I achieve this without reflection?

    Come to that, how should the Windows Forms team have written BindingSource?

  • User profile image
    vesuvius

    If i've read you right, you need string-indexed funtionality. Best use the dictionary class, where you have key(index), value(string) pairs.

    That looks the best way to me.

  • User profile image
    TypeSpafe

    Sorry, you've either misunderstood my post or I needed a better example of a business object:

    class Person : BusinessObject<Person>
    {
        private string forename;
        public string Forename
        {
            get { return this.forename; }
            set
            {
                this.forename = value.ToUpper();
                // And some other stuff...
            }
        }
    }
    ...
    Person person = new Person();
    person["Forename"] = "bob";
    // person.Forename is now "BOB"

    The indexer provides access to the actual property, with all the functionality therein. There are also helper classes to return information about the properties within the objects, which mean the application supports user-designed wizards, reporting and other features. None of this is possible without reflection.

  • User profile image
    Yggdrasil

    TypeSpafe wrote:
    indexer provides access to the actual property, with all the functionality therein. There are also helper classes to return information about the properties within the objects, which mean the application supports user-designed wizards, reporting and other features. None of this is possible without reflection.


    Since you're dealing with a fixed subset of properties that are known to the business object code, the simplest way is to have static mappings from strings to properties.
    I'm all for reflection when necessary, don't get me wrong. I just think that in this case you can simply offload the mapping logic to the objects that implement the particular properties.

    class BusinessObject
    {
       public string Name { get; set;}
      
       public virtual string this[string propertyName]
       {
          set 
          {
             switch (propertyName)
             {
                 case "Name": this.Name = value; break;
                 default: throw new ArgumentException("Unknown property");
             }
          }
       }
    }

    class Person : BusinessObject
    {
         public string Address { get; set;}
         
         public override string this[string propertyName]
         {
             switch (propertyName)
             {
                 case "Address": this.Address = value;
                 default: base[propertyName] = value;
             }
         }
    }

  • User profile image
    TypeSpafe

    Yeah, I considered that, but it adds to the complexity of the code. There are going to be something like 250 business objects with an average of 20 properties in each, and even though they're generated, it's still a bunch more code.

    If I hit performance issues I'll add overrides for the relevant classes, but since these indexers are used in fairly low-volume operations like web binding, I'm not worried at the moment.

    Actually, even if I was doing that, I'd still be tempted to use Emit to generate the switch methods at runtime.

    Plus, it's nice to have it built into the framework functionality instead of the generator.

  • User profile image
    longnight


    It might work if you add a function like this to your "MyStringClass"

      public static implicit operator  MyInterface<Object>( MyStringClass s )
      {
       return s;
      }

    Edit: oops, that causes a stack overflow

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.