|
-
September 17th, 2011, 10:33 AM
#1
Generics conversion problem
I've got an conversion issue with converting an instance to a certain class. This instance is created after I scanned my assembly for a certain type. Don't ask why I'm doing this in complex way. I've got a very good reason for it. Trust me .
I've place three conversions in the code. The third one isn't working but should be correct. Does anybody knows a trick to get the third conversion working too.
Tnx.
@@csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ReflectionTest2
{
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.GetExecutingAssembly();
// Get all types which implement IElementUpdater
List<Type> typeToChecks = assembly.GetTypes().Where
(t => ((typeof(IElementUpdater).IsAssignableFrom(t)
&& t.IsClass && !t.IsAbstract))).ToList();
foreach (Type typeToCheck in typeToChecks)
{
var instance = MyObjectFactory.CreateObject(typeToCheck);
// Conversion works fine but I'm not able to call the Foo method
IElementUpdater one = instance as IElementUpdater;
// Conversion works fine but is only to proof it is of the correct type
SaleElementUpdateHandler two = instance as SaleElementUpdateHandler;
// Conversie doesn't work
IElementUpdater<IBaseTransactionElement> three = instance as IElementUpdater<IBaseTransactionElement>;
}
}
}
public interface IBaseTransactionElement
{
}
public interface IElementUpdater
{
}
public interface IElementUpdater<T> : IElementUpdater where T : IBaseTransactionElement
{
void Foo(T element);
}
public class SaleElementUpdateHandler : IElementUpdater<FooBar>
{
#region IElementUpdater<FooBar> Members
public void Foo(FooBar element)
{
throw new NotImplementedException();
}
#endregion
}
public class FooBar : IBaseTransactionElement
{
}
}
@@
-
September 19th, 2011, 07:52 AM
#2
Re: Generics conversion problem
It is because generics in C# don't support covariance and contravariance (althought CLR does). You can cast the instance to IElementUpdater<FooBar>, but not to IElementUpdater<IBaseTransactionElement>, despite that FooBar implements IBaseTransactionElement.
- Make it run.
- Make it right.
- Make it fast.
Don't hesitate to rate my post. 
-
September 19th, 2011, 12:00 PM
#3
Re: Generics conversion problem
Thanks for your reply and answer. I understand why it doesn't work. Could it be made possible by implementing iconvertible or something similar?
Tnx for your effort.
-
September 20th, 2011, 02:49 AM
#4
Re: Generics conversion problem
There is a solution, or better workaround, which is explicit interface implementation.
Code:
public class SaleElementUpdateHandler : IElementUpdater<FooBar>, IElementUpdater<IBaseTransactionElement>
{
#region IElementUpdater<FooBar> Members
public void Foo(FooBar element)
{
throw new NotImplementedException();
}
#endregion
#region IElementUpdater<IBaseTransactionElement> Members
void IElementUpdater<IBaseTransactionElement>.Foo(IBaseTransactionElement element)
{
throw new NotImplementedException();
}
#endregion
}
- Make it run.
- Make it right.
- Make it fast.
Don't hesitate to rate my post. 
-
September 20th, 2011, 02:10 PM
#5
Re: Generics conversion problem
Hmmmm....I'm sorry but I don't find this a real solution.
The nice thing about generics is that my Foo method will always receive a strong typed object. No conversion is needed. With the extra method I'll always have to a cast which can anything if it a IBaseTransactionElement.
public void Foo(IBaseTransactionElement element)
{
this.Foo(element as FooBar);
}
I've already solved my problem with reflection. My provider class will load all classes of type IElementUpdater<T> and stores the methodinfo of the interface itself.
MethodInfo mi = typeToCheck.GetMethod("Foo");
After that it's just a matter of invoking the MethodInfo. I've been told invoking is slighty slower but I don't think it will matter in our case.
Cheers.
-
September 20th, 2011, 04:15 PM
#6
Re: Generics conversion problem
 Originally Posted by KiwiDre
I've been told invoking is slighty slower but I don't think it will matter in our case.
Reflection and invoking is way slower. It pretty much should be used as a last resort.
-
September 20th, 2011, 04:32 PM
#7
Re: Generics conversion problem
Way slower?? How much slower?? Do you have any info about the performance loss?
The reflection part is done once and that's it. I'll do a test to see how much slower the invoke is.
!!!UPDATE!!!
SMALL TEST COMPLETED
And the results are:
Function call direct duration (#Iterations: 100000)
Elapsed time: 00:00:00.0006791
Elapsed milliseconds: 0
Elapsed ticks: 2039
Function call invoke duration (#Iterations: 100000)
Elapsed time: 00:00:00.0977379
Elapsed milliseconds: 97
Elapsed ticks: 293439
This is much more than I anticipated. Nevertheless, I don't think it will be a bottleneck for us. And if it is we might start use Boudino's approach.
Last edited by KiwiDre; September 20th, 2011 at 04:51 PM.
-
September 21st, 2011, 12:18 PM
#8
Re: Generics conversion problem
Search bing or google for "reflection performance".
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|