protected Type CreateProxyType(Type type)
        {
            if (type.GetConstructor(new Type[0]) == null)
            {
                throw new PatchProxyTypeException($"Type {type} doesn't have an empty constructor.");
            }

            RuntimeTypeBuilder proxyBuilder = new RuntimeTypeBuilder($"{{Guid.NewGuid()}}.{type.FullName}Patch", type);

            FieldBuilder modified      = proxyBuilder.DefineField("_modified", typeof(HashSet <string>), FieldAttributes.Private);
            var          modifiedField = Field(proxyBuilder.This, modified);

            foreach (PropertyInfo propInfo in type.GetRuntimeProperties())
            {
                if (propInfo.CanRead && propInfo.CanWrite && propInfo.GetSetMethod().IsVirtual)
                {
                    ParameterExpression valueExpr = Parameter(propInfo.PropertyType, "value");

                    var baseGet = Call(proxyBuilder.Base, propInfo.GetGetMethod());

                    proxyBuilder.OverrideMethod(propInfo.GetSetMethod(),
                                                new[] { valueExpr },
                                                If(NotEqual(baseGet, valueExpr),
                                                   Then(
                                                       If(IsNull(modifiedField),
                                                          Assign(modifiedField, New(typeof(HashSet <string>)))
                                                          ),
                                                       Call("Add", modifiedField, Constant(propInfo.Name)),
                                                       Call(proxyBuilder.Base, propInfo.SetMethod, valueExpr)
                                                       )
                                                   )
                                                );
                }
            }

            proxyBuilder.DefineMethod("Reset", null,
                                      Block(
                                          If(IsNotNull(modifiedField),
                                             Call("Clear", modifiedField)
                                             )
                                          )
                                      );

            var propNameParam = Parameter(typeof(string), "propName");

            proxyBuilder.DefineMethod("IsSet",
                                      new[] { propNameParam },
                                      Block(
                                          Variable("result", Constant(false), out Expression result),
                                          If(IsNotNull(modifiedField),
                                             Assign(result, Call("Contains", modifiedField, propNameParam))
                                             ),
                                          Result(result)
                                          )
                                      );

            proxyBuilder.AutoImplementInterface(typeof(IPatch));

            return(proxyBuilder.Create());
        }
Beispiel #2
0
        public void auto_implement_interface()
        {
            RuntimeTypeBuilder typeBuilder = new RuntimeTypeBuilder("AutoImplenetInterface", typeof(BasePropertyClass));

            typeBuilder.AutoImplementInterface(typeof(ITextProperty));

            Type          newType     = typeBuilder.Create();
            ITextProperty newInstance = (ITextProperty)Activator.CreateInstance(newType);

            newInstance.Text = "test text";

            Assert.Equal("test text", newInstance.Text);
        }
Beispiel #3
0
        public void define_autoproperty()
        {
            RuntimeTypeBuilder typeBuilder = new RuntimeTypeBuilder("DefineAutoProperty");

            typeBuilder.DefineAutoProperty("TestProp", typeof(int));

            Type   newType     = typeBuilder.Create();
            object newInstance = Activator.CreateInstance(newType);

            PropertyInfo testPropInfo = newType.GetProperty("TestProp");

            testPropInfo.SetValue(newInstance, 5);
            int result = (int)testPropInfo.GetValue(newInstance);

            Assert.Equal(5, result);
        }
Beispiel #4
0
        public void call_base_method()
        {
            RuntimeTypeBuilder typeBuilder = new RuntimeTypeBuilder("CallBaseMethod", typeof(BaseMethodClass));
            MethodInfo         getTextInfo = typeof(BaseMethodClass).GetMethod("GetText");

            typeBuilder.OverrideMethod(getTextInfo,
                                       null,
                                       Call("Concat", typeof(string), Call(typeBuilder.Base, getTextInfo), Constant(" (overriden)"))
                                       );

            Type   newType     = typeBuilder.Create();
            object newInstance = Activator.CreateInstance(newType);

            MethodInfo testMethodInfo = newType.GetMethod("GetText");
            object     result         = testMethodInfo.Invoke(newInstance, null);

            Assert.Equal("this is the base class! (overriden)", result);
        }
Beispiel #5
0
        public void override_property()
        {
            RuntimeTypeBuilder typeBuilder = new RuntimeTypeBuilder("OverrideProperty", typeof(BasePropertyClass));

            PropertyInfo propInfo = typeof(BasePropertyClass).GetProperty("Text");

            typeBuilder.OverrideMethod(propInfo.GetGetMethod(),
                                       null,
                                       Call("Concat", typeof(string), Call(typeBuilder.Base, propInfo.GetGetMethod()), Constant(" (overriden)"))
                                       );

            Type   newType     = typeBuilder.Create();
            object newInstance = Activator.CreateInstance(newType);

            propInfo.SetValue(newInstance, "this is a property!");
            string result = (string)propInfo.GetValue(newInstance);

            Assert.Equal("this is a property! (overriden)", result);
        }
Beispiel #6
0
        public void define_method()
        {
            RuntimeTypeBuilder  typeBuilder = new RuntimeTypeBuilder("DefineMethod");
            ParameterExpression a           = Parameter(typeof(int), "a");
            ParameterExpression b           = Parameter(typeof(int), "b");

            typeBuilder.DefineMethod("TestMethod",
                                     new[] { a, b },
                                     Add(a, b)
                                     );

            Type   newType     = typeBuilder.Create();
            object newInstance = Activator.CreateInstance(newType);

            MethodInfo testMethodInfo = newType.GetMethod("TestMethod");
            object     result         = testMethodInfo.Invoke(newInstance, new object[] { 5, 4 });

            Assert.Equal(9, result);
        }
Beispiel #7
0
        public void access_local_field()
        {
            RuntimeTypeBuilder  typeBuilder = new RuntimeTypeBuilder("AccessLocalField");
            ParameterExpression a           = Parameter(typeof(int), "a");
            ParameterExpression b           = Parameter(typeof(int), "b");

            var field = typeBuilder.DefineField("TestField", typeof(string));

            typeBuilder.DefineMethod("TestMethod",
                                     null,
                                     Field(typeBuilder.This, field)
                                     );

            Type   newType     = typeBuilder.Create();
            object newInstance = Activator.CreateInstance(newType);

            FieldInfo fieldInfo = newType.GetField("TestField");

            fieldInfo.SetValue(newInstance, "testValue");
            MethodInfo testMethodInfo = newType.GetMethod("TestMethod");
            object     result         = testMethodInfo.Invoke(newInstance, null);

            Assert.Equal("testValue", result);
        }