I am trying to create a run-time mock, which will have a specific behaviour for every method, which will be called. For example this mock should always return null - which is already working - or raise an exception for a not reachable database or in this specific case throw an Argument Exception.
I know, that this could be done fairly easy with a mocking framework. But since I have to use this via Spring.NET, I can not use a mocking framework, as far as I know. This is because I have to give a type into the StaticApplicationContext. If there is an easier way to create mock types, let me know.
The code below will throw an Expected:
But was: (Common Language Runtime detected an invalid program.)
at TypeMock.Foo()
at TypeBuilderTest.
public interface IInterfaceWithObject
{
String Foo();
}
[Test]
public void MinimalExample()
{
//build expression
var constructorInfo = typeof(ArgumentNullException).GetConstructor(new Type[0]);
Assert.IsNotNull(constructorInfo);
Expression expression = Expression.Throw(Expression.New(constructorInfo));
//create type
// based upon https://stackoverflow.com/questions/38345486/dynamically-create-a-class-by-interface
var ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run);
var mb = ab.DefineDynamicModule("Test");
TypeBuilder typeBuilder = mb.DefineType("TypeMock");
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
typeBuilder.AddInterfaceImplementation(typeof(IInterfaceWithObject));
List<MethodInfo> methods = new List<MethodInfo>(typeof(IInterfaceWithObject).GetMethods());
foreach (Type interf in typeof(IInterfaceWithObject).GetInterfaces())
{
foreach (MethodInfo method in interf.GetMethods())
if (!methods.Contains(method))
methods.Add(method);
}
foreach (var imethod in methods)
{
var parameters = imethod.GetParameters();
List<Type> parameterTypes = new List<Type>();
foreach (var parameter in parameters)
{
parameterTypes.Add(parameter.ParameterType);
}
var method =
typeBuilder.DefineMethod
(
"##" + imethod.Name,
MethodAttributes.Public | MethodAttributes.Static,
imethod.ReturnType,
parameterTypes.ToArray()
);
var thisParameter = Expression.Parameter(typeof(IInterfaceWithObject), "this");
var bodyExpression = Expression.Lambda
(expression
,
thisParameter
);
bodyExpression.CompileToMethod(method);
var stub =
typeBuilder.DefineMethod(imethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, imethod.ReturnType, parameterTypes.ToArray());
var il = stub.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, method, null);
il.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(stub, imethod);
}
Type type = typeBuilder.CreateType();
//create instance via spring.net
StaticApplicationContext context = new StaticApplicationContext();
MutablePropertyValues value = new MutablePropertyValues();
string objectName = "Integer";
context.RegisterSingleton(objectName, type, value);
var objectInstance = (IInterfaceWithObject)context.GetObject(objectName);
Assert.Throws<ArgumentNullException>(() => objectInstance.Foo());
}
Related
I'm trying to migrate a project from CommandLineParser to newer System.CommandLine.
CommandLineParser uses attributes on the handler classes and attributes on properties for options, while System.CommandLine expects all verbs and options to be part of a RootCommand.
What I'm trying to do is emulate the attribute structure and creating ad-hoc Handlers for my classes, so I don't have to locate each attribute and make it work with the newer package, also it lacks extensibility imho.
The problem: System.CommandLine doesn't seem to accept my built delegate (using LINQ Expressions) because of the way it tries to bind options to delegate parameters, it uses reflection on Delegate.Method.GetParameters(), and in the case of built delegates, this includes a System.Runtime.CompilerServices.Closure type parameter, which totally baffles the binding process.
I also tried to call the CommandHandler builder that takes the delegate methodinfo and target, to be welcomed with another error:
foreach (var verbType in Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetCustomAttributes(typeof(VerbAttribute), false).Length > 0))
{
var attr = verbType.GetCustomAttribute<VerbAttribute>();
var verb = new Command(attr.Verb, attr.HelpText);
IEnumerable<PropertyInfo> props = verbType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy).Where(pi => pi.GetCustomAttributes(typeof(OptionAttribute), true).Length > 0);
MethodInfo runMethod = verbType.GetMethod("Run", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
Delegate handler = BuildDelegate(props, runMethod, verbType);
verb.Handler = CommandHandler.Create(handler); // Runtime Error trying to bind Delegate.Method.GetParameters()
verb.Handler = CommandHandler.Create(handler.Method, handler.Target); // runtime error: "MethodInfo must be a runtime MethodInfo object"
}
I'd like to know if this parameter can be eliminated, or what could be done to migrate.
This is my code to build delegates: (expects a Run() method to be created on the handler class)
private static readonly TextInfo _textInfo = CultureInfo.InvariantCulture.TextInfo;
// props: the discovered properties with an Option attribute
// runMethod: the discovered Run method
// instanceType: Type of the handler class
private static Delegate BuildDelegate(IEnumerable<PropertyInfo> props, MethodInfo runMethod, Type instanceType)
{
List<ParameterExpression> parms = new();
List<MemberBinding> binds = new();
foreach (PropertyInfo pi in props)
{
ParameterExpression parm = Expression.Parameter(pi.PropertyType, _lowerCamel(pi.Name));
parms.Add(parm);
MemberBinding bind = Expression.Bind(pi, parm);
binds.Add(bind);
}
Expression self = Expression.MemberInit(Expression.New(instanceType), binds);
LambdaExpression lambda = Expression.Lambda(_getCall(self, runMethod), parms);
return lambda.Compile();
static Expression _getCall(Expression self, MethodInfo runMethod)
{
IEnumerable<Expression> runArgs =
runMethod.GetParameters().Select(pInfo => Expression.Constant(pInfo.DefaultValue, pInfo.ParameterType));
return Expression.Call(self, runMethod, runArgs);
}
static string _lowerCamel(string s)
{
string title = _textInfo.ToTitleCase(_textInfo.ToLower(s));
char[] chars = s.ToCharArray();
chars[0] = _textInfo.ToLower(chars[0]);
return new string(chars);
}
}
I have a list with instances of a dynamic type created using reflection. The dynamic type has properties with names that contain a period like HELLO.WORLD. These properties are of type string.
My goal is to select those properties with LINQ using Select
If i try the following
var lstResult = ((IEnumerable<dynamic>)mydynamicdata).Select(d => d.HELLO.WORLD).AsEnumerable().ToList();
I get the error that the collection does not have HELLO property. Any idea how to select this property? Basically I need a list of string as a result.
Creation of dynamic type
private object CreateDynamicObject(IEnumerable<string> columnsNames)
{
Type dynamicType = GetDynamicType(columnsNames);
object generetedObject = Activator.CreateInstance(dynamicType);
return generetedObject;
}
private Type CreateDynamicObjectType(IEnumerable<string> columnNames)
{
// create a dynamic assembly and module
var assemblyName = new AssemblyName { Name = "tmpAssembly" };
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder module = assemblyBuilder.DefineDynamicModule("tmpModule");
// create a new type builder
TypeBuilder typeBuilder = module.DefineType("BindableRow", TypeAttributes.Public | TypeAttributes.Class);
foreach (var header in columnNames)
{
AddProperty(typeBuilder, header, typeof(string));
}
// Generate our type
Type generetedType = typeBuilder.CreateType();
return generetedType;
}
private void AddProperty(TypeBuilder typeBuilder, string propertyName, Type type)
{
FieldBuilder field = typeBuilder.DefineField("_" + propertyName, typeof(string), FieldAttributes.Private);
// Generate a public property
PropertyBuilder property = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, type, null);
// The property set and property get methods require a special set of attributes:
const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
// Define the "get" accessor method for current private field.
MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_" + property.Name, getSetAttr, type, Type.EmptyTypes);
// Intermediate Language stuff...
ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
// Define the "set" accessor method for current private field.
MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_" + property.Name, getSetAttr, null, new Type[] { type });
// Again some Intermediate Language stuff...
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
// Last, we must map the two methods created above to our PropertyBuilder to
// their corresponding behaviors, "get" and "set" respectively.
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
}
The following is a screenshot from the debugger
http://i.imgur.com/eydF46P.png
You can access dynamic like a dictionary:
var lstResult = ((IEnumerable<dynamic>)mydynamicdata).Select(d => d["HELLO.WORLD"]).AsEnumerable().ToList();
If this is not working, this might help: https://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.trygetindex.aspx
One solution is to use again reflection to get the value
((IEnumerable<dynamic>)mydynamicdata).Select(d => GetPropValue(d,"COMO.NAME")).AsEnumerable().ToList();
and the GetPropValue function
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
But actually the original question has not still an answer...
is there any way how to actually get to the CSSpace in entity framework 6 code first?
I tried to convert DbContext to ObjectContext like this:
public static ObjectContext ToObjectContext(this DbContext dbContext)
{
return ((IObjectContextAdapter)dbContext).ObjectContext;
}
but how can I get access to the CSSpace via the ObjectContext?
thanks for answers, any help would be appreciated, I tried a lot but it seems that nothing works :/
I was having the same problem and came across a few links online which I tweaked and build the extension methods below. TableMapping and ColumnMapping are just simple classes I use to store the translation data, so you can just ignore those.
I adapted snippets of Måns Tånneryd code from his answer here
(half way down).
The biggest issue with CSSpace is that most of the information you need is not exposed. Thus the most useful part of this is the use of reflection to get array and property data. Hopefully, this help. feel free to ping me if you need any further explanation.
public static IEnumerable<TableMapping> GetMappings(this DbContext context)
{
List<TableMapping> tableMappings = new List<TableMapping>();
var storageMapping = ((IObjectContextAdapter)context).ObjectContext.MetadataWorkspace.GetItem<GlobalItem>(((IObjectContextAdapter)context).ObjectContext.DefaultContainerName, DataSpace.CSSpace);
dynamic entitySetMaps = storageMapping.GetType().InvokeMember(
"EntitySetMaps",
BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance,
null, storageMapping, null);
foreach (var entitySetMap in entitySetMaps)
{
var typeMappings = GetArrayList("EntityTypeMappings", entitySetMap);
dynamic typeMapping = typeMappings[0];
dynamic types = GetArrayList("Types", typeMapping);
var fragments = GetArrayList("MappingFragments", typeMapping);
var fragment = fragments[0];
var tableSet = GetProperty("TableSet", fragment);
var tableName = GetProperty("Name", tableSet);
TableMapping tm = new TableMapping
{
Entity = context.FindContextTableName((string)types[0].Name),
Table = tableName
};
var properties = GetArrayList("AllProperties", fragment);
List<ColumnMapping> columnMappings = new List<ColumnMapping>();
foreach (var property in properties)
{
var edmProperty = GetProperty("EdmProperty", property);
var columnProperty = GetProperty("ColumnProperty", property);
ColumnMapping cm = new ColumnMapping
{
Property = edmProperty.Name,
Column = columnProperty.Name
};
columnMappings.Add(cm);
}
tm.Columns = columnMappings.AsEnumerable();
tableMappings.Add(tm);
}
return tableMappings.AsEnumerable();
}
private static ArrayList GetArrayList(string property, object instance)
{
var type = instance.GetType();
var objects = (IEnumerable)type.InvokeMember(
property,
BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, instance, null);
var list = new ArrayList();
foreach (var o in objects)
{
list.Add(o);
}
return list;
}
private static dynamic GetProperty(string property, object instance)
{
var type = instance.GetType();
return type.InvokeMember(property, BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null, instance, null);
}
I am using Reflection.Emit and I want to create a type that would be the equivalent of the following type defined in C#:
class A
{
public Tuple<A, int> GetValue(int x)
{
return new Tuple<A, int>(this, x);
}
}
The trick is that I need to use a generic type from BCL that uses my custom type as a generic argument.
I'm messing with the following snippet:
var asmName = new AssemblyName("Test");
var access = AssemblyBuilderAccess.Run;
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, access);
var module = asm.DefineDynamicModule("Test");
var aType = module.DefineType("A");
var tupleType = typeof(Tuple<,>).MakeGenericType(aType, typeof(int));
var attrs = MethodAttributes.Public;
var method = aType.DefineMethod("GetValue", attrs, tupleType, new [] { typeof(int) });
var gen = method.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
// here is the fail:
var ctor = tupleType.GetConstructor(new [] { typeof(int), aType } );
gen.Emit(OpCodes.Newobj, ctor);
The call to GetConstructor fails with the following exception:
NotSupportedException: Specified method is not supported.
So, basically, it won't let me get the constructor of a type that merely references my custom type, and neither can I finalize the type before emitting the body of its method.
Can it really be impossible to get out of this vicious circle?
For some reason, you need to use the static overload of GetConstructor() to do this. In your case, the code could look like this:
var ctor = TypeBuilder.GetConstructor(
tupleType, typeof(Tuple<,>).GetConstructors().Single());
Toying with making a compiler for my own language, I'm trying to generate some MSIL code using the Reflection.Emit framework. It works fine when using int when I declare local variables. However, when I want to declare a local variable of a type I have not yet compiled I get into trouble since the DeclareLocal() takes a Type as argument. That is my uncompiled class, say A, still needs to be defined using
assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemName, AssemblyBuilderAccess.RunAndSave);
module = assemblyBuilder.DefineDynamicModule(Filename);
module.DefineType(name, TypeAttributes.Public | TypeAttributes.Class)
So how will I ever be able to compile the following program
class A {
void M() { B b = new B(); }
}
class B
void M() { A a = new A(); }
}
The primary insight you need here is that TypeBuilder derives from Type. So, even if you didn't finalize a type yet (by calling CreateType()), you can use it to declare a local variable in another type.
One more barrier I encountered is that GetConstructor() on an unfinished TypeBuilder doesn't work (it throws an exception). But if you create the default constructor explicitly, you can call it through the ConstructorBuilder.
static void Main()
{
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave);
var module = assemblyBuilder.DefineDynamicModule("foo.dll");
var aType = module.DefineType(
"A", TypeAttributes.Public | TypeAttributes.Class);
var bType = module.DefineType(
"B", TypeAttributes.Public | TypeAttributes.Class);
var aCtor = aType.DefineDefaultConstructor(MethodAttributes.Public);
var bCtor = bType.DefineDefaultConstructor(MethodAttributes.Public);
CreateMethodM(aType, bType, bCtor);
CreateMethodM(bType, aType, aCtor);
aType.CreateType();
bType.CreateType();
assemblyBuilder.Save("foo.dll");
}
static void CreateMethodM(
TypeBuilder thisType, Type otherType, ConstructorInfo otherCtor)
{
var method = thisType.DefineMethod(
"M", MethodAttributes.Private, typeof(void), Type.EmptyTypes);
var il = method.GetILGenerator();
var local = il.DeclareLocal(otherType);
il.Emit(OpCodes.Newobj, otherCtor);
il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ret);
}