Hi all,

I've create an attribute and try to use his field value in his method. Here 
what i've done :


The attribute
[AttributeUsage(AttributeTargets.Method)]
    public class CA_WriteLine : Attribute
    {
        public object _arg;
        public CA_WriteLine(object arg)
        {
            _arg = arg;
        }

        public void CA_PreInject(params object[] parametters)
        {
            if (parametters != null && parametters.Length > 0 && 
parametters[0].GetType() == typeof(string))
            {
                Console.WriteLine(parametters[0]);
            }
        }
    }

The implementation
class Program
    {
        static void Main(string[] args)
        {
            Test_WriteLine("Hello World !");
            Console.ReadKey();
        }

        [CA_WriteLine("Test WriteLine")]
        public static void Test_WriteLine(string message)
        {
            Console.WriteLine(message);
        }
    }

The patch
static void Main(string[] args)
        {
            //Get args to patch the DLL
            string assemblyDirectory = "";
            string assemblyFilename = "";
            if(args == null || args.Length != 2)
            {
                throw new ArgumentException("Please give the right 
arguments (AssemblyDirectory; AssemblyFilename)");
            }

            assemblyDirectory = args[0];
            assemblyFilename = args[1];

            //Get CecileAttributes
            TypeDefinition writeLineTypeReference = 
GetWriteLineMethodReference();

            //Load assembly
            AssemblyDefinition assembly = 
AssemblyDefinition.ReadAssembly(assemblyDirectory + assemblyFilename);

            //Patch assembly methods foreach CecileAttributes attributes 
found
            CustomAttribute attr = null;
            foreach (var moduleDefinition in assembly.Modules)
            {
                foreach (var type in 
ModuleDefinitionRocks.GetAllTypes(moduleDefinition))
                {
                    foreach (var method in type.Methods)
                    {
                        if ((attr = GetAttributeByName("CA_WriteLine", 
method.CustomAttributes)) != null)
                        {
                            MethodDefinition writeLineReference = 
writeLineTypeReference.Methods.FirstOrDefault(m => 
m.FullName.Contains("CA_PreInject"));
                            ILProcessor ilProcessor = 
method.Body.GetILProcessor();
                            
ilProcessor.InsertBefore(method.Body.Instructions.First(), 
ilProcessor.Create(OpCodes.Call, method.Module.Import(writeLineReference)));
                            FieldDefinition fld = 
writeLineTypeReference.Fields[0];
                            
ilProcessor.InsertBefore(method.Body.Instructions.First(), 
ilProcessor.Create(OpCodes.Ldarg_0));
                            
ilProcessor.InsertBefore(method.Body.Instructions.First(), 
ilProcessor.Create(OpCodes.Ldfld, method.Module.Import(fld)));
                        }
                    }
                }
            }

            assembly.Write(assemblyDirectory + 
@"\CecileAttributesTest2.exe");
        }

        private static bool HasAttribute(string attributeName, 
IEnumerable<CustomAttribute> customAttributes)
        {
            return GetAttributeByName(attributeName, customAttributes) != 
null;
        }

        private static CustomAttribute GetAttributeByName(string 
attributeName, IEnumerable<CustomAttribute> customAttributes)
        {
            foreach (var attribute in customAttributes)
                if 
(attribute.AttributeType.FullName.Contains(attributeName))
                    return attribute;
            return null;
        }

        private static TypeDefinition GetWriteLineMethodReference()
        {
            AssemblyDefinition attributeAssemblyDefinition = 
AssemblyDefinition.ReadAssembly(@"C:\Users\XXX\Documents\visual studio 
2015\Projects\CecilAttributes\CecileAttributes\obj\Debug\CecileAttributes.dll");
            Collection<TypeDefinition> attributeTypes = 
attributeAssemblyDefinition.MainModule.Types;

            return attributeTypes.FirstOrDefault(a => 
a.FullName.Contains("CA_WriteLine"));
        }
    }


The goal is that Ca_WriteLine:CA_PreInject is called before 
Program:TestWriteLine using the given parametter.
I don't really understand how get a field and give it, or give an object as 
parametter. It is a bit hard to understand to me.

Can you help me ?

Thanks !


-- 
-- 
--
mono-cecil
--- 
You received this message because you are subscribed to the Google Groups 
"mono-cecil" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to