简体   繁体   中英

Create a custom ASP.NET (not MVC) directive possible?

I'm working on a somewhat advanced custom framework for some websites I'm developing at work, and I'm implementing a small plugin system for it. I want to register the plugins somehow in the ASPX file so I can then hook into the different page events (Load, PreRender, etc.) after calling them in sequence in my Page_Init function, for example. I'll jump straight to the code so you see what I want to do:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Plugin TypeName="MyFramework.Plugin.Core" Arg1="arg1" Arg2="arg2" %>
<%@ Plugin TypeName="MyFramework.Plugin.MainMenu" Arg1="arg1" Arg2="arg2" %>
<%@ Plugin TypeName="MyFramework.Plugin.IE6Hacks" Arg1="arg1" Arg2="arg2" %>
<%@ Plugin TypeName="MyFramework.Plugin.Footer2015" Arg1="arg1" Arg2="arg2" %>
<%@ Plugin TypeName="MyFramework.Plugin.SortableGridViews" Arg1="arg1" Arg2="arg2" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>blah</title>
</head>
<body>      
    <form id="form1" runat="server"> Blah... </form>
</body>
</html>

See those <% Plugin %> directives? they don't exist in ASP.NET but I want to create them. I can't find anything on google regarding this stuff. Is it possible to create a custom one?

My idea is that once they're "registered" with those directives, I can loop through all of them (either stored in an array everytime the directive is hit, or in the Page_Init event) and act accordingly.

Another idea I had was to use code blocks instead:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<% RegisterPlugin("MyFramework.Plugin.Core"); %>
<% RegisterPlugin("MyFramework.Plugin.MainMenu"); %>
<% RegisterPlugin("MyFramework.Plugin.IE6Hacks"); %>
<% RegisterPlugin("MyFramework.Plugin.Footer2015"); %>
<% RegisterPlugin("MyFramework.Plugin.SortableGridViews"); %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title>blah</title>
</head>
<body>      
    <form id="form1" runat="server"> Blah... </form>
</body>
</html>

BUT the functions get called after all the page events instead of running before them (or at least before Page_Load) leaving me with no way of detecting if I have plugins registered in order to act accordingly in my base page's Page_Load events and such.

Any ideas are really appreciated :). Thanks in advance!

The ASP.NET page parser doesn't support custom directives (although it does support custom attributes on the Page or MasterPage directive). But you still can do what you want using server controls.

Let's suppose you have a base plugin class, like this:

// we derive from control, so all plugins are automatically
// added to the Page.Controls collection
public class MyPluginBase : Control
{
}

And for example, two plugin classes like this:

public class MyPlugin : MyPluginBase
{
    public string MyFirstProperty { get; set; }
    public int MySecondProperty { get; set; }
}

public class MyOtherPlugin : MyPluginBase
{
    public string MyFirstProperty { get; set; }
    public int MySecondProperty { get; set; }
}

Then you can write an ASPX webform (or an ASCX) like this:

<%@ Page ... standard attributes ... %>

<plugins:MyPlugin runat="server" MyFirstProperty="blah" MySecondProperty="1"></plugins:MyPlugin>
<plugins:MyOtherPlugin runat="server" MyFirstProperty="blahblah" MySecondProperty="2"></plugins:MyOtherPlugin>

etc...

Note for this to work, you'll have to declare the plugins prefix somewhere, for example in the web.config, like this:

<configuration>
  <system.web>
    <pages>
      <controls>
        <!-- all assemblies & namespaces that contain plugins classes -->
        <add assembly="WebApplication1" namespace="WebApplication1.Code" tagPrefix="plugins" />
        <add assembly="MyOtherPlugins" namespace="MyOtherPlugins.Plugins" tagPrefix="plugins" />
      </controls>
    </pages>
  </system.web>
</configuration>

And in the code behind class, you'll have automatic access to the plugins, in all events including Init, with a code like this:

public partial class WebForm1 : Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        // get all plugins on the page
        var plugins = Controls.OfType<MyPluginBase>();
    }
}

Use a dependency injection container like Autofac that has support for WebForms .

You're probably going to be interested in using the Enumeration or Metadata Integerrogation relationship types to accomplish your plugin registration/resolution.

You might also find some traction using MEF with WebForms. WebForms and MEF Sample

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM