mercredi 19 août 2009

BuildProvider : Custum compilation ASP.NET

L’ASP.NET est extensible de multiple façon : IHttpHandler & Factory’s, les contrôles ASP.NET. Mais l’extension la plus intéressante du moteur ASP.NET est la compilation personnalisé.
Comment cela marche t-il ? Grâce à BuilderProvider. La classe BuilderProvider va nous permettre de compiler du code sur le même principe que l’ASP.NET avec les pages ASPX, ASCX, Master, etc. On va donc créer un générateur pour une extension de fichier définie dans la configuration et le moteur ASP.NET se chargera de compiler le code généré et l’intégrer dans notre application au démarrage de celle-ci.

Étape 1 : Génération du code source et création du provider de génération :

public class SampleBuildProvider : BuildProvider
{
private CompilerType _compilerType = null;

public SampleBuildProvider()
{
_compilerType = base.GetDefaultCompilerTypeForLanguage("C#");
}

public override CompilerType CodeCompilerType
{
get { return _compilerType; }
}

public override void GenerateCode(AssemblyBuilder assemblyBuilder)
{
using (TextWriter wr = assemblyBuilder.CreateCodeFile(this))
{
wr.WriteLine("using System;");
wr.WriteLine("using System.Collections.Generic;");
wr.WriteLine("using Builder;");

wr.WriteLine("namespace MyNamespace");
wr.WriteLine("{");
Uri uri = new Uri(base.VirtualPath);
wr.WriteLine("public class My{0} : IHttpHandler", Path.GetFileName(base.VirtualPath).Split(new char[] { '.' }));
wr.WriteLine("{");

// Implémentation de IHttpHandler

wr.WriteLine("}}");
}
}

public override Type GetGeneratedType(CompilerResults results)
{
string type = string.Format("MyNamespace.My{0}", Path.GetFileName(base.VirtualPath).Split(new char[] { '.' }));
return results.CompiledAssembly.GetType(type);
}
}

Étape 2 : Spécifier dans la section “Compilation” du Web.Config quels sont les fichiers concernés :

<compilation debug="true">
<buildProviders>
<
add type="SampleBuildProvider" extension=".myExt"/>
</
buildProviders>
</
compilation>

Étape 3 : Utilisation des éléments générés :

Dans notre exemple, on implémente IHttpHandler, il nous suffit de créer alors un Factory de Handler pour cette nouvelle extension :

[PermissionSet(SecurityAction.LinkDemand, Unrestricted = true), PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
public class MyHandlerFactory : IHttpHandlerFactory
{
public MyHandlerFactory()
{
}

public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
{
Type type = BuildManager.GetCompiledType(virtualPath);
return Activator.CreateInstance(type) as IHttpHandler;
}

public virtual void ReleaseHandler(IHttpHandler handler)
{
}
}

et de le spécifier dans la configuration :

<httpHandlers>
<
add verb="*" path="*.sb" type="MyHandlerFactory"/>
</
httpHandlers>

On peut trouver de multiples applications, les plus courrantes vont utiliser le Xml pour décrire du code.

0 commentaires:

Enregistrer un commentaire