Hi, i also use Cecil for Property change notification. Here is me code
that works (I also read
http://justinangel.net/AutomagicallyImplementingINotifyPropertyChanged)
The only difference is that I search for NotifyProperty attribute.
Code works with cecil 0.9.1
private void SearchForPropertiesAndAddMSIL()
{
List<string> finishedAssemblies = new List<string>();
try
{
bool hasMVVMAttribute;
List<PropertyDefinition> replaceProperties = new
List<PropertyDefinition>();
foreach (string assemblyPath in
Directory.GetFiles(SolutionDir, "*.exe", SearchOption.AllDirectories))
{
if
(finishedAssemblies.Contains(Path.GetFileName(assemblyPath)))
continue;
//Console.WriteLine(assemblyPath);
BuildEngine2.LogMessageEvent(new
BuildMessageEventArgs(assemblyPath, "", "", MessageImportance.High));
if (assemblyPath.Contains("MVVM") ||
assemblyPath.Contains("SharpSvn") ||
assemblyPath.Contains("INPCShadowCopies"))
continue;
if
(assemblyPath.Contains("WeavingINPC.MSBuildTask.dll") ||
assemblyPath.Contains("vshost"))
continue;
hasMVVMAttribute = false;
bool _isDirty = false;
string shadowCopyPath = CreateCopy(assemblyPath);
AssemblyDefinition sourceAssembly =
AssemblyDefinition.ReadAssembly(shadowCopyPath, new ReaderParameters
{
SymbolReaderProvider = new
PdbReaderProvider(),
});
foreach (TypeDefinition type in
sourceAssembly.MainModule.Types)
{
if (type.FullName.Contains("ViewModel"))
foreach (PropertyDefinition prop in
type.Properties)
foreach (CustomAttribute attribute in
prop.CustomAttributes)
{
if
(attribute.Constructor.DeclaringType.FullName ==
typeof(NotifyProperty).FullName)
{
MethodDefinition
raisePropertyChanged = null;
foreach (MethodDefinition
method in type.Methods)
{
if (method.Name ==
"OnPropertyChanged" && method.Parameters.Count == 1 &&
method.Parameters[0].ParameterType.FullName == "System.String")
{
raisePropertyChanged =
method;
break;
}
}
if (raisePropertyChanged ==
null)
{
foreach (MethodDefinition
method in ((Mono.Cecil.TypeDefinition)(type.BaseType)).Methods)
{
if (method.Name ==
"OnPropertyChanged" && method.Parameters.Count == 1 &&
method.Parameters[0].ParameterType.FullName == "System.String")
{
raisePropertyChanged = method;
break;
}
}
if (raisePropertyChanged
== null)
{
BuildEngine2.LogErrorEvent(new BuildErrorEventArgs("", "", "", 0, 0,
0, 0, "Could not find OnPropertyChanged(string) method in" +
type.FullName, "", ""));
continue;
}
}
if (replaceProperties.Any(p =>
p.DeclaringType.FullName == prop.DeclaringType.FullName && p.Name ==
prop.Name))
{
continue;
}
ILProcessor MSILWorker =
prop.SetMethod.Body.GetILProcessor();
Instruction
callRaisePropertyChanged = MSILWorker.Create(OpCodes.Call,
raisePropertyChanged);
if
(prop.SetMethod.Body.Instructions.Contains(callRaisePropertyChanged))
break;
Instruction ldarg0 =
MSILWorker.Create(OpCodes.Ldarg_0);
Instruction propertyName =
MSILWorker.Create(OpCodes.Ldstr, prop.Name);
MSILWorker.InsertBefore(prop.SetMethod.Body.Instructions[prop.SetMethod.Body.Instructions.Count
- 1], ldarg0);
MSILWorker.InsertAfter(ldarg0,
propertyName);
MSILWorker.InsertAfter(propertyName, callRaisePropertyChanged);
MSILWorker.InsertAfter(callRaisePropertyChanged,
MSILWorker.Create(OpCodes.Nop));
//
BuildEngine2.LogMessageEvent(new
BuildMessageEventArgs(string.Format("Added INotifyPropertyChanged
invoke for {0}.{1}", prop.DeclaringType.FullName, prop.Name), "", "",
MessageImportance.High));
replaceProperties.Add(prop);
_isDirty = true;
}
}
}
if (_isDirty)
{
using (FileStream stream = new FileStream("D:\
\HomeProjects\\PM.snk", FileMode.Open))
{
try
{
sourceAssembly.Write(shadowCopyPath,
new WriterParameters
{
SymbolWriterProvider = new
PdbWriterProvider(),
StrongNameKeyPair = new
StrongNameKeyPair(stream)
});
}
catch (Exception ex)
{
BuildEngine2.LogErrorEvent(new
BuildErrorEventArgs("", "", "", 0, 0, 0, 0, ex.Message, "", ""));
}
stream.Close();
}
finishedAssemblies.Add(Path.GetFileName(assemblyPath));
}
}
}
catch (Exception ex)
{
BuildEngine2.LogErrorEvent(new BuildErrorEventArgs("",
"", "", 0, 0, 0, 0, ex.Message, "", ""));
}
}
--
--
mono-cecil