How to combine a) MEF and Generics in MEF composition engine? - c#

I have the below program in MEF
Method 1:
public ObjectResult<PartnerListingStatement> GetCommissionListingRecords(string uRL, PortalConstant.DataSourceType DataSourceType)
{
ObjectResult<PartnerListingStatement> lstCommissionPartner = null;
var dataPlugin = DataPlugins.FirstOrDefault(i => i.Metadata["SQLMetaData"].ToString() == DataSourceType.EnumToString());
if (dataPlugin != null)
{
lstCommissionPartner = dataPlugin.Value.GetCommissionListingRecords(uRL);
}
return lstCommissionPartner;
}
Method B
public ObjectResult<CommissionEarned> GetCommissionPaidToPartners(string uRL, PortalConstant.DataSourceType DataSourceType)
{
ObjectResult<CommissionEarned> lstCommissionEarned = null;
var dataPlugin = DataPlugins.FirstOrDefault(i => i.Metadata["SQLMetaData"].ToString() == DataSourceType.EnumToString());
if (dataPlugin != null)
{
lstCommissionEarned = dataPlugin.Value.GetCommissionPaidToPartners(uRL);
}
return lstCommissionEarned;
}
Using generics or the like can these two be combined. Also the data types are different.
N.B.~ This question is different than Generics program to access WCF service from client
Thanks

The first question to ask after asking "Can I combine these methods?" is "What do these methods have in common?" I your case, the answer to that would be something like this:
public ObjectResult<***SomeType***> GetValues(string uRL, PortalConstant.DataSourceType DataSourceType)
{
ObjectResult<***SomeType***> ret = null;
var dataPlugin = DataPlugins.FirstOrDefault(i => i.Metadata["SQLMetaData"].ToString() == DataSourceType.EnumToString());
if (dataPlugin != null)
{
ret = dataPlugin.Value.***SomeMethod***(uRL);
}
return ret;
}
where ***SomeType*** and ***SomeMethod*** are the two meaningful differences between the methods. The deal with the type, make the method generic and replace all the ***SomeType*** with the generic parameter. To deal with the method, add a delegate parameter to the method. Based on its usage, the delegate will be of the Func<PluginType, string, ObjectResult<***SomeType***>> type where PluginType is whatever type dataPlugin.Value is. Now you have:
public ObjectResult<T> GetValues<T>( //do come up with a better name
string uRL,
PortalConstant.DataSourceType DataSourceType,
Func<PluginType, string, ObjectResult<T>> resultSelector)
{
ObjectResult<T> ret = null;
var dataPlugin = DataPlugins.FirstOrDefault(i => i.Metadata["SQLMetaData"].ToString() == DataSourceType.EnumToString());
if (dataPlugin != null)
{
ret = resultSelector(dataPlugin.Value, uRL);
}
return ret;
}
which is changes GetCommissionListingRecords to (the generic type should be inferred)
GetValues(uRL, DataSourceType, (p, u) => p.GetCommissionListingRecords(u));
and similarly for the other method.

Related

How to Build Expression Tree for Invoke Method from Generic Interface

I'm sorry to ask, how can i invoke method using other that method.Invoke, because some article said, method.Invoke has slower performance.
Actually i'm using .NET Core 3.1.
Example, i have a structure code something like this.
public class Message { }
public class MyMessageType : Message { }
public class MyMessageResult
{
public bool Status { get; set; }
public DateTime Date => DateTime.Now;
}
public interface IEncapsulatedMessageHandlerV2<T, TResult> where T : class
{
Task<TResult> HandleMessageResultAsync(T message);
}
public abstract class EncasulatedMessageHandlerV2<T, TResult> : IEncapsulatedMessageHandlerV2<T, TResult> where T : Message
{
public abstract Task<TResult> HandleMessageResultExecAsync(T message);
async Task<TResult> IEncapsulatedMessageHandlerV2<T, TResult>.HandleMessageResultAsync(T message)
{
var msg = message as T;
if (msg != null)
return await HandleMessageResultExecAsync(msg);
return default;
}
}
public class HandlerV2 : EncasulatedMessageHandlerV2<MyMessageType, MyMessageResult>
{
public override Task<MyMessageResult> HandleMessageResultExecAsync(MyMessageType message)
{
Console.WriteLine("Yo Async!");
return Task.FromResult(new MyMessageResult
{
Status = true
});
}
}
And i can successfully call using method.Invoke
static TResponse UsingMethodInvoke<TResponse>()
{
// Assume, i was build this using MakeGenericMethod
var type = typeof(IEncapsulatedMessageHandlerV2<MyMessageType, MyMessageResult>);
var typeActivator = typeof(HandlerV2);
var instance = Activator.CreateInstance(typeActivator);
var method = type.GetMethod("HandleMessageResultAsync");
var tsk = (Task<TResponse>)method.Invoke(instance, new[] { new MyMessageType() });
var result = tsk.GetAwaiter().GetResult();
return result;
}
And i try to using Dynamic too, unfortunately they can't calling through abstract HandleMessageResultAsync instead only through implemented class HandleMessageResultExecAsync
static TResponse UsingDynamicInvoke<TResponse>()
{
// Assume, i was build this using MakeGenericMethod
var typeActivator = typeof(HandlerV2);
var instance = Activator.CreateInstance(typeActivator);
var tsk = (Task<TResponse>)((dynamic)instance).HandleMessageResultExecAsync(new MyMessageType());
var result = tsk.GetAwaiter().GetResult();
return result;
}
And i was follow to with stackoverflow Speeding up Reflection Invoke C#/.NET, and i get stuck
static void ActivatorMyMessageResultAsnc()
{
var type = typeof(HandlerV2);
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("HandleMessageResultAsync", BindingFlags.Instance | BindingFlags.Public);
var originalType = type;
// Loop until we hit the type we want.
while (!(type.IsGenericType) || type.GetGenericTypeDefinition() != typeof(EncasulatedMessageHandlerV2<,>))
{
type = type.BaseType;
if (type == null)
throw new ArgumentOutOfRangeException("type");
}
var messageType = type.GetGenericArguments()[0]; // MyMessageType
// Use expression to create a method we can.
var instExpr = Expression.Parameter(typeof(object), "instance");
var paramExpr = Expression.Parameter(typeof(Message), "message");
// (Handler)instance;
var instCastExpr = Expression.Convert(instExpr, originalType);
// (MyMessageType)message
var castExpr = Expression.Convert(paramExpr, messageType);
// ((Handler)inst).HandleMessage((MyMessageType)message)
var invokeExpr = Expression.Call(instCastExpr, method, castExpr); // <--- this give me error
// i'm stuck, i don't know what should i do next
////// Assume this is build from MakeGeneric too
////var delType = typeof(Func<object, Message, Task<MessageResult>>);
//var lambda = Expression.Lambda<Func<object, Message, Task<object>>>(invokeExpr, instExpr, paramExpr);
//var compiled = lambda.Compile();
//Func<Message, Task<object>> hook = x => compiled(instance, x);
Or, is there any other ways to Invoke method by dynamicaly, which is faster that method.Invoke
Thanks in advance,
PS: Sorry for my Bad English
I had a similar problem I was trying to solve a while back. I dug into the Net Core codebase and found a class which is really helpful for invoking methods at runtime without being strongly typed.
https://github.com/dotnet/extensions/blob/ff87989d893b000aac1bfef0157c92be1f04f714/shared/Microsoft.Extensions.ObjectMethodExecutor.Sources/ObjectMethodExecutor.cs
ObjectMethodExecutor lets you call a method on an object using its name. An example of usage is:
var methodInfo = [myInterface].GetMethod("[method-you-want-call]");
var classTypeInfo = [myClass].GetTypeInfo();
var executor = ObjectMethodExecutor.Create(methodInfo, classTypeInfo);
await executor.ExecuteAsync(handler, new[] { [data-you-want-to-pass-to-your-object] });
Its used extensively in the SignalR codebase for matching SignalR messages to the internal methods on a hub. Its heavily optimised and has the added benefit of allowing async methods to be called too

Simplifying an expression selector

At the moment i am using this code in a class i call "Ensure", it is essentially a shortcut class of static methods i use to make throwing exceptions easier, so i am not constantly having to write out a minimum of 3 lines to do an exception, it can all always be done on 1 line.
[DebuggerHidden, DebuggerStepThrough]
public static void ArgumentNotNull(object argument, string name)
{
if (argument == null)
{
throw new ArgumentNullException(name, "Cannot be null");
}
}
[DebuggerHidden, DebuggerStepThrough]
public static void ArgumentNotNull<T>(Expression<Func<T>> expr)
{
var e = (MemberExpression)expr.Body;
var val = GetValue<T>(e);
ArgumentNotNull(val, e.Member.Name);
}
My issue is, currently when calling Ensure.ArgumentNotNull, i either have to do:
Ensure.ArgumentNotNull(arg, "arg");
or
Ensure.ArgumentNotNull(() => arg);
As i need the name to be able to explain which argument caused the exception in the exception its self.
Is there a way of being able to call ArgumentNotNull without needing the () => part of the lambda and simply call Ensure.ArgumentNotNull(arg) and still be able to get the name of the argument that was passed, without having to specifically pass the name as well.
Is there a way of being able to call ArgumentNotNull without needing the () => part of the lambda and simply call Ensure.ArgumentNotNull(arg) and still be able to get the name of the argument that was passed
I doubt it, because values have no meta-data to determine if it was an argument passed in, a variable, or a literal. The value will not always be an argument - there's nothing preventing you from calling Ensure.ArgumentNotNull(null);.
this works
public static void ArgumentNotNull(object argument)
{
StackFrame stackFrame = new StackTrace(true).GetFrame(1);
string fileName = stackFrame.GetFileName();
int lineNumber = stackFrame.GetFileLineNumber();
var file = new System.IO.StreamReader(fileName);
for (int i = 0; i < lineNumber - 1; i++)
file.ReadLine();
string varName = file.ReadLine().Split(new char[] { '(', ')' })[1];
if (argument == null)
{
throw new ArgumentNullException(varName, "Cannot be null");
}
}
alternate answer to OP question
'and still be able to get the name of the argument that was passed, without having to specifically pass the name as well.'
Simplified lamdba will do the trick.
myObject.ArgumentNotNull(x=>x.SomeProperty); -- prop checking
myObject.ArgumentNotNull(x=>x); -- objchecking
[DebuggerHidden, DebuggerStepThrough]
public static void ArgumentNotNull<T>(this T obj, Expression<Func<T, object>> expr = null)
{
if (obj == null) throw new NullReferenceException();
var body = expr.Body as MemberExpression;
if (body == null)
{
var ubody = (UnaryExpression)expr.Body;
body = ubody.Operand as MemberExpression;
}
if (body != null)
{
var property = body.Member as PropertyInfo;
if (property == null) throw;
if (obj.GetType().GetProperty(property.Name).GetValue(obj, null) == null) throw new NullReferenceException();
}
else
{
var ubody = (UnaryExpression)expr.Body;
var property = ubody.Operand as MemberExpression;
if (property != null)
props[property.Member.Name] = obj.GetType()
.GetProperty(property.Member.Name)
.GetValue(obj, null);
if (obj.GetType().GetProperty(property.Member.Name).GetValue(obj, null) == null) throw new NullReferenceException();
}
}
I am not aware of any mechanism you could use for this without some degree of code clutter, except for the Fody.NullGuard mentioned by Aron (opt-out model only) and other AOP frameworks (PostSharp).
However, instead of using expression trees, which both result in significant runtime performance penalty and are limited in terms of syntax, you can use anonymous types. This approach is relatively good in terms of performance, with a couple of assumptions:
that the user of the API will use it for arguments assertion only
that details of anonymous types implementation in C# will not change significantly
The usage of the API will look something like:
void SomeMethod(object arg1, string arg2, List<int> arg3)
{
new { arg1, arg2, arg3 }.ShouldNotBeNull();
....
Implementation is too large to show here, so it can be found in this gist. Additionally, it can be extended for range validations, etc.
You really want to use Fody.NullGuard instead of your current solution if you are worried about making a mistake when calling throw new ArgumentNullException("argName");.
You use Fody.NullGuard like this
public class Sample
{
public void SomeMethod(string arg)
{
// throws ArgumentNullException if arg is null.
}
public void AnotherMethod([AllowNull] string arg)
{
// arg may be null here
}
}
After compilation, Fody will rewrite the IL so its functionally the same as
public class Sample
{
public void SomeMethod(string arg)
{
if(arg == null)
throws new ArgumentNullException("arg");
}
public void AnotherMethod(string arg)
{
}
}

Can a delegate take a generic as a parameter

I've created a class that works with my cache to get cached items. If the items are not cached then it calls a function to get the actual value.
This class has eight methods, all with almost identical code except for the function they call. I've created a function called GetObject which takes a delegate to call if it can't find an item in the class.
I can't get my code to compile because of the following error:
Argument 2: cannot convert from
'System.Collections.Generic.List<string>' to
'MyFunction<System.Collections.Generic.List<string>>'.
Am I doing something wrong or am I'm trying to do something that can't be done?
Here's the code I'm trying.
public delegate T MyFunction<T>(string s);
public T GetCultures<T>(string s) where T : class {
return NewListOfStrings(s) as T;
}
public List<string> NewListOfStrings(string s) {
return new List<string> { s };
}
public List<string> GetListOfStrings(string sitename) {
string key = cachingService.CreateValidKey("stringvalue");
//This is the line that fails to compile
var foundItems = GetObject<List<string>>(key,
GetCultures<List<string>>(sitename));
return foundItems;
}
public T GetObject<T>(string key, MyFunction<T> f) where T : class {
T foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
lock (key) {
foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
foundItems = f as T;
if (foundItems != null) {
cachingService.SetCachedItem(key, foundItems, 5,
Constants.MINUTES);
}
}
}
}
return foundItems;
}
Solution
public T GetObject<T>(string key, Func<T> getFromRepository) where T : class {
T foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
lock (key) {
foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
foundItems = getFromRepository() as T;
if (foundItems != null) {
cachingService.SetCachedItem(key, foundItems, 5,
Constants.MINUTES);
}
}
}
}
return foundItems;
}
public AreaModels.Site GetSiteByName(string sitename) {
string key = cachingService.CreateValidKey(
string.Format("Site_{0}", sitename));
return GetObject<AreaModels.Site>(key,
() => efRepository.GetSiteByName(sitename));
}
public List<AreaModels.Culture> GetCulturesForSite(string sitename) {
string key = cachingService.CreateValidKey(
string.Format("Cultures_{0}", sitename));
return GetObject<List<AreaModels.Culture>>(key,
() => efRepository.GetCulturesForSite(sitename));
}
public List<AreaModels.Resource> Resources(string sitename, int appId) {
string key = cachingService.CreateValidKey(
string.Format("ResourcesFor{0}", sitename));
return GetObject<List<AreaModels.Resource>>(key,
() => efRepository.GetResourcesBySiteAndAppId(sitename, appId));
}
You're passing the result of the function rather than the function itself. You can use a lambda like so:
var foundItems = GetObject<List<string>>(key,
name => GetCultures<List<string>>(sitename));
You also have this line:
foundItems = f as T;
Here you're trying to cast the function itself to its return type, which won't work. Instead you could do:
foundItems = f(name);
But now your problem is that you'd have to pass the name into GetObject, because otherwise it won't be accessible where it's needed. The reason for this is there's a mismatch between MyFunction, which takes a string, and what you actually want, which is a function that can be evaluated within GetObject without needing the name parameter to be passed in.
So what you should really do is change your delegate to:
public delegate T MyFunction<T>();
Or alternatively get rid of the delegate altogether and have the f parameter be a Func<T>.
With either of these options, you can pass in the lamba with no parameter required:
var foundItems = GetObject<List<string>>(key,
() => GetCultures<List<string>>(sitename));
And evaluate it like:
foundItems = f();
Note that it's a bit roundabout to create a lambda to pass it into another method just to then evaluate it, rather than just passing the result in directly. So unless there's some reason that you need to do this in some cases, you might instead want to change the f parameter to take a type T instead. In this case I suspect you're doing it to lazily evaluate the function so that you don't have to evaluate if the result is already cached. That would probably be a valid reason, assuming you're not optimizing for performance prematurely.
You aren't creating a delegate. You are actually evaluating the method before calling GetObject. Easily fixed:
var foundItems = GetObject<List<string>>(key,
name => GetCultures<List<string>>(name));
Note also that it isn't obvious what you want to do with sitename in this scenario; you might instead mean this:
name => GetCultures<List<string>>(sitename));
Here's a complete example
public class TestDelegate
{
//You don't need generic here if you always return a list of string
public List<string> GetCulture(string s)
{
return new List<string> { s };
}
public T GetObject<T>(string key, Func<string, T> fn)
{
T foundItems = fn(key);
return foundItems;
}
public void Test()
{
List<string> test = GetObject("abc", x => GetCulture(x));
}
}
If you look at the method Test() and GetObject(), you can note 3 interesting things :
You don't have to specify the generic type on GetObject() because the compiler infer it from GetCulture()
The x parameter serves as an input to your delegate function, that way the method
GetObject can use the "key" and pass it to the delegate function.
I replace your delegate function by "Func" with a string input and a List output.

How to wrap a static class in a non-static instance object (dynamically)

I have an interesting problem. I need to wrap static classes dynamically. I.e. return a non-static instance to my callers. e.g.:
public object CreateInstance(string className) {
Type t = assembly.GetType(className);
if (IsStatic(t)) {
return CreateStaticWrapper(t);
} else {
return Activator.CreateInstance(t);
}
}
So what I need is pointers as to how to implement CreateStaticWrapper.
Note: I cannot use Dynamic objects unfortunately.
So what are my options? I'm not that keen on learning IL generation? If IL generation (Reflection.Emit, or is there other ways now?) is the way to go does anyone have pointers there?
Edit: It's important to note that I can return a Dictionary of Delegates. So I could use Delegate.CreateDelegate for this but I can't seem to work out how to handle overloaded methods and Generic methods.
Edit2: Another option would be to inject an empty constructor into the type using Emit, again any pointers? Is this even possible on a type marked as static? Does the static keyword make it into the IL?
Edit3: For a bit of context, I'm passing this to a javascript environment see: my project. So I would like to be able to (in JavaScript):
var fileHelper = .create('System.IO.File');
if (fileHelper.Exists(fileName)) { fileHelper.Delete(fileName); }
Thanks All.
Try creating a wrapper class which inherits from System.Dynamic.DynamicObject. In the wrapper class, use reflection to call the methods of the static class.
You need something like this:
public class StaticWrapper<T> : System.Dynamic.DynamicObject
{
private static readonly Type t = typeof(T);
public static int MyProperty { get; set; }
public override bool TryInvokeMember(System.Dynamic.InvokeMemberBinder binder, object[] args, out object result)
{
try
{
result = t.InvokeMember(binder.Name, BindingFlags.Static | BindingFlags.Public, null, null, args);
return true;
}
catch
{
result = null;
return false;
}
}
public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
{
try
{
var p = t.GetProperty(binder.Name);
if (p != null)
result = p.GetValue(null, null);
else
{
var f = t.GetField(binder.Name);
if (f != null) result = f.GetValue(null);
else { result = null; return false; }
}
return true;
}
catch
{
result = null;
return false;
}
}
public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value)
{
try
{
var p = t.GetProperty(binder.Name);
if (p != null)
p.SetValue(null, value, null);
else
{
var f = t.GetField(binder.Name);
if (f != null) f.SetValue(null, value);
else return false;
}
return true;
}
catch (SystemException)
{
return false;
}
}
}
Hope it works.
I'd say go for IL generation. Creating a proxy is a pretty simple scenario. I actually wrote a blog post about it: einarwh.posterous.com/patching-polymorphic-pain-at-runtime. The scenario is different, but the solution almost identical.
You can basically do exactly as in the blog post, except you don't need to load the 'this' reference onto the stack (since you're doing static method calls).
Ok, well the solution I've come up with is as follows and was found reading through and studying Einar's blog post which he posted as a comment above. Thanks Einar.
But I thought I'd post my full code solution here in case it may help someone in the future:
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
namespace js.net.jish.Command
{
public class StaticTypeWrapper
{
private readonly Type staticType;
public StaticTypeWrapper(Type staticType)
{
this.staticType = staticType;
}
public object CreateWrapper()
{
string ns = staticType.Assembly.FullName;
ModuleBuilder moduleBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(ns), AssemblyBuilderAccess.Run).DefineDynamicModule(ns);
TypeBuilder wrapperBuilder = moduleBuilder.DefineType(staticType.FullName, TypeAttributes.Public, null, new Type[0]);
foreach (MethodInfo method in staticType.GetMethods().Where(mi => !mi.Name.Equals("GetType")))
{
CreateProxyMethod(wrapperBuilder, method);
}
Type wrapperType = wrapperBuilder.CreateType();
object instance = Activator.CreateInstance(wrapperType);
return instance;
}
private void CreateProxyMethod(TypeBuilder wrapperBuilder, MethodInfo method)
{
var parameters = method.GetParameters();
var methodBuilder = wrapperBuilder.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, parameters.Select(p => p.ParameterType).ToArray());
var gen = methodBuilder.GetILGenerator();
for (int i = 1; i < parameters.Length + 1; i++)
{
gen.Emit(OpCodes.Ldarg, i);
}
gen.Emit(OpCodes.Call, method);
gen.Emit(OpCodes.Ret);
}
}
}
So, say that we play around with the "Delegate.CreateDelegate" way. And let's see if we can get more details about your other issues after that... Let's start with:
public static object Generate(Type t)
{
if(IsStatic(t))
{
var dictionary = new Dictionary<string, Delegate>();
foreach (var methodInfo in t.GetMethods())
{
var d = Delegate.CreateDelegate(t, methodInfo);
dictionary[methodInfo.Name] = d;
}
return dictionary;
}
return Activator.CreateInstance(t);
}
Static classes are 'sealed' and can thus not be inherited. So I don't see what you mean by 'overloaded'. For generic methods, we need to invoke the methodInfo.MakeGenericMethod(...) before adding it to our dictionary. But then you would need to know the type beforehand, which I guess you don't... Alternatively, you can do something like:
...
if (methodInfo.IsGenericMethod)
{
d = new Func<MethodInfo, Type[], Delegate>(
(method, types) =>
Delegate.CreateDelegate(
method.DeclaringType, method.MakeGenericMethod(types)));
}
dictionary[methodInfo.Name] = d;
...
That would give you a delegate that would take a type array (the generic type parameters), and produce a working delegate from that.

Arg<object>.Is.Equal with anonymous objects

In my MVC3 project, I use an IUrlProvider interface to wrap the UrlHelper class. In one of my controller actions, I have a call like this:
string url = _urlProvider.Action("ValidateCode", new { code = "spam-and-eggs" });
I want to stub this method call in my unit test, which is in a separate project. The test setup looks something like this:
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<object>.Is.Equal(new { code = "spam-and-eggs" }) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
Unfortunately, Arg<object>.Is.Equal(new { code = "spam-and-eggs" }) doesn't work, because new { code = "spam-and-eggs" } != new { code = "spam-and-eggs" } when the anonymous types are declared in different assemblies.
So, is there an alternative syntax I can use with Rhino Mocks to check for matching field values between anonymous objects across assemblies?
Or should I replace the anonymous object declarations with a class, like this?
public class CodeArg
{
public string code { get; set; }
public override bool Equals(object obj)
{
if(obj == null || GetType() != obj.GetType())
{
return false;
}
return code == ((CodeArg)obj).code;
}
public override int GetHashCode()
{
return code.GetHashCode();
}
}
string url = _urlProvider.Action("ValidateCode",
new CodeArg { code = "spam-and-eggs" });
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<CodeArg>.Is.Equal(new CodeArg { code = "spam-and-eggs" }) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
EDIT
If my unit test was in the same project as my controller, comparing the anonymous objects would work fine. Because they are declared in separate assemblies, they will not be equal, even if they have the same field names and values. Comparing anonymous objects created by methods in different namespaces doesn't seem to be a problem.
SOLUTION
I replaced Arg<object>.Is.Equal() with Arg<object>.Matches() using a custom AbstractConstraint:
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<object>.Matches(new PropertiesMatchConstraint(new { code = "spam-and-eggs" })) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
public class PropertiesMatchConstraint : AbstractConstraint
{
private readonly object _equal;
public PropertiesMatchConstraint(object obj)
{
_equal = obj;
}
public override bool Eval(object obj)
{
if (obj == null)
{
return (_equal == null);
}
var equalType = _equal.GetType();
var objType = obj.GetType();
foreach (var property in equalType.GetProperties())
{
var otherProperty = objType.GetProperty(property.Name);
if (otherProperty == null || property.GetValue(_equal, null) != otherProperty.GetValue(obj, null))
{
return false;
}
}
return true;
}
public override string Message
{
get
{
string str = _equal == null ? "null" : _equal.ToString();
return "equal to " + str;
}
}
}
Anonymous types do implement Equals and GetHashCode in a pretty normal way, calling GetHashCode and Equals for each of their submembers.
So this should pass:
Assert.AreEqual(new { code = "spam-and-eggs" },
new { code = "spam-and-eggs" });
In other words, I suspect you're looking for the problem in the wrong place.
Note that you have to specify the properties in exactly the right order - so new { a = 0, b = 1 } will not be equal to new { b = 1, a = 0 }; the two objects will be of different types.
EDIT: The anonymous type instance creation expressions have to be in the same assembly, too. This is no doubt the problem in this case.
If Equals allows you to specify an IEqualityComparer<T>, you could probably build one which is able to compare two anonymous types with the same properties by creating an instance of one type from the properties of an instance of the other, and then comparing that to the original of the same type. Of course if you were using nested anonymous types you'd need to do that recursively, which could get ugly...
As GetValue returns a boxed value, this appears to work correctly.
public class PropertiesMatchConstraint : AbstractConstraint
{
private readonly object _equal;
public PropertiesMatchConstraint(object obj)
{
_equal = obj;
}
public override bool Eval(object obj)
{
if (obj == null)
{
return (_equal == null);
}
var equalType = _equal.GetType();
var objType = obj.GetType();
foreach (var property in equalType.GetProperties())
{
var otherProperty = objType.GetProperty(property.Name);
if (otherProperty == null || !_ValuesMatch(property.GetValue(_equal, null), otherProperty.GetValue(obj, null)))
{
return false;
}
}
return true;
}
//fix for boxed conversions object:Guid != object:Guid when both values are the same guid - must call .Equals()
private bool _ValuesMatch(object value, object otherValue)
{
if (value == otherValue)
return true; //return early
if (value != null)
return value.Equals(otherValue);
return otherValue.Equals(value);
}
public override string Message
{
get
{
string str = _equal == null ? "null" : _equal.ToString();
return "equal to " + str;
}
}
}

Categories