You can get it to work this way too
using System;
using System.IO;
using Csla;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MemoryStream ms = new MemoryStream();
Console.WriteLine(ms.GetType());
Console.WriteLine("-----------------------------");
Foo.FetchChildTest();
Console.WriteLine("-----------------------------");
var t = typeof(Program);
var foo = t.GetMethod("foo");
Csla.Reflection.MethodCaller.CallMethod(new Program(), foo, "hi there");
Console.Read();
}
public void foo(MemoryStream ms)
{
Console.WriteLine(ms.GetType());
}
}
class Foo : BusinessBase<Foo>
{
public static Foo FetchChildTest()
{
return DataPortal.FetchChild<Foo>("SomeString");
}
private void Child_Fetch(System.IO.MemoryStream ms)
{
Console.WriteLine(ms.GetType());
}
}
}
I think it may be because CSLA doesn't actually use reflection. It uses dynamic method invocation, and so creates IL code that directly calls the method. Perhaps some of these cast restrictions don't exist at the .NET runtime level itself, but are constructs of our 3GL programming languages and their compilers.
While this is academically interesting, it doesn't block normal usage of the data portal, so trying to address it is far from a high priority.
But I did refer this to my colleague Jason Bock, who's always interested in clever IL behaviors, so I'll be interested to see what his thoughts are when he has time to look into it.
If there's an easy tweak to the IL we're creating for the dynamic method invocation that'd be fine. But if CSLA has to do a bunch more reflection or something expensive to detect and block this sort of obscure scenario I'm less interested in solving it.
Though I suppose we could accept a broader breaking change that would be a cheap fix. The data portal tries to find an exact match for the method you call. But if it can't, it falls back to a method with the same number of parameters. This avoids a more expensive operation where I'd have to walk each parameter type to see if the types are convertable, which would almost certainly cause serious perf issues.
But what I could do instead, is just throw an exception if no exact match is found. That would prevent the use of base types in the target methods - which might easily break some existing code - but would block the scenario you are seeing here.
rxelizondo:
My simplistic view tells me that we should take whatever performance hit we need to take in order for things to function the way they are supposed to function to be able to avoid these types of scenarios.
If this wasn't about data access I might agree. Like at the UI layer I have no problem using reflection, because data binding already uses reflection and saving a millisecond here and there rarely matters.
But when it comes to data access perf and efficiency are much more important. Those milliseconds lost are not only lost to the user getting the data, but to other users waiting to leverage the same app server, so the cost is much higher.
Decreasing perf in the data portal is risky - enough decrease and people (rightly so) would question whether to use CSLA at all. So I could make the framework "correct" but entirely useless - and that would certainly not be a win :)
If there's a way to make it correct without a perf cost, that's the way to go. Or maybe lose some features to be correct - again assuming those features don't make the framework useless for a measurable percentage of the user base.
But you must admit, the fact that it is even possible to get .NET to (successfully) invoke a method with the wrong parameter type is really kind of cool :)
RockfordLhotka:
But when it comes to data access perf and efficiency are much more important. Those milliseconds lost are not only lost to the user getting the data, but to other users waiting to leverage the same app server, so the cost is much higher.
Decreasing perf in the data portal is risky - enough decrease and people (rightly so) would question whether to use CSLA at all. So I could make the framework "correct" but entirely useless - and that would certainly not be a win :)
Though you'll be happy to know that Jason generally agrees with you :)
Hopefully we can find some better IL to use in the dynamic proxy so the CLR throws the expected exception at this point.
Copyright (c) Marimer LLC