Wednesday, May 9, 2012

Run-time assembly creation

There are times where you may need to generate Assembly dynamically at run-time.  The blog post shares some code for the same.

public CompilerResults Compile()
{
//Set the compiler options
var compilerOptions = new Dictionary<string, string>();
compilerOptions.Add("CompilerVersion", "v4.0");

CodeDomProvider compiler = new CSharpCodeProvider(compilerOptions);
CompilerParameters parameters = new CompilerParameters();
parameters.WarningLevel = 4;
parameters.TreatWarningsAsErrors = false;
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = false;
parameters.OutputAssembly = GetFileName();
parameters.IncludeDebugInformation = false;
if (RoleEnvironment.IsAvailable)
parameters.TempFiles = new TempFileCollection(RoleEnvironment.GetLocalResource("CompilerTempFiles").RootPath, false);

string baseDir = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
baseDir = baseDir.Substring(0,
baseDir.LastIndexOf(Path.DirectorySeparatorChar));
baseDir = baseDir.Substring(0,
baseDir.LastIndexOf(Path.DirectorySeparatorChar));

//Add required assembly references of your code
string assemblyName;
foreach (string assembly in GetReferences())
{
string suffix = assembly.EndsWith(".exe") ? "" : ".dll";

assemblyName = assembly;
if (!assembly.StartsWith("System"))
{
if (assembly.IndexOf(".dll") > -1)
{
assemblyName = FindAssembly(baseDir, assembly);
suffix = "";
}
parameters.ReferencedAssemblies.Add(assemblyName + suffix);
}
else
{
var assemblyPath = (from assm
in AppDomain.CurrentDomain.GetAssemblies()
where assm.FullName.IndexOf(assemblyName + ",") > -1
select assm).FirstOrDefault();

if (assemblyPath == null)
{
throw new Exception("Unable to locate assembly: "
+ assemblyName + suffix);
}

parameters.ReferencedAssemblies.Add(assemblyPath.Location);
}
}

//Get your dynamic code
string Code = GetCodeText();

CompilerResults results = compiler.CompileAssemblyFromSource(
parameters, Code);

return results;
}





With dynamic code you must have some known interface, so that you can create the dynamic object of given interface to invoke the code.

public IKnownInterface GetTableServiceContext()
{
string assemblyPath = GetFileName();
if (!File.Exists(assemblyPath))
{
throw new FileNotFoundException(assemblyPath + " not found");
}

System.Reflection.Assembly assem = AppDomain.CurrentDomain.Load(
File.ReadAllBytes(assemblyPath));

Type queryType = assem.GetType("DynamicClassName");

return Activator.CreateInstance(queryType) as IKnownInterface;
}





We should be avoiding dynamic code generation and look for solutions like dependency injection, MEF frameworks.

Teams PowerShell

 The PowerShell helps to get quick meta data around Teams. Install-Module -Name MicrosoftTeams Connect-MicrosoftTeams Get-TeamAllChannel...