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.