Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving ASP.NET Web Forms Image Control derived class registered via Simple Injector

I'm about to inject a repository instance into some Web.UI.WebControls.Image derived type:

public class CustomImageControl : Image
{
    [Import]
    public ICachedNameRepository Repo { get; set; } // Null reference here

    private void DynamicImage_PreRender(object sender, EventArgs e)
    {
        ImageUrl = {some ICachedNameRepository usage}
    }
}

Also here is my default page I have implemented for testing purposes:

public partial class _Default : Page
{
    [Import]
    public ICachedNameRepository Repo { get; set; } // Totally ok here

    protected void Page_Load(object sender, EventArgs e)
    {
        {some ICachedNameRepository usage}
    }
}

I have implemented container bootstraping according to official guide with respect of usage Control registering instead of Page:

    private void BootStrapContainer()
    {
        var container = new Container();
        container.Options.PropertySelectionBehavior = new ImportAttributePropertySelectionBehavior();            

        container.Register<ICachedNameRepository, CachedNameRepository>();
        container.Register<CustomImageControl>(); // Also I have tried Control and Image types
        container.Register<Page>();
        var cc = container.GetInstance<CustomImageControl>(); // Correctly instantiated CachedNameRepository instance in Repo field in cc object

        container.Verify(); // OK here
        Global.Container = container;
    }

I left ControlInitializerModule, ImportAttributePropertySelectionBehavior and InitializeHandler routines completely copypasted from guide mentioned earlier

At page loading I ended up with correctly resolved default page instance with CachedNameRepository injected into the right place, but my CustomImageControl suffering from null reference.

like image 781
Sergey Prytkov Avatar asked Feb 22 '26 16:02

Sergey Prytkov


1 Answers

This can be done by hooking into the InitComplete event of the Page. This is the code I've used to prove this.

I changed CustomImageControl to inherit from UserControl:

public partial class CustomImageControl : UserControl
{
    [Import]
    public ICachedNameRepository Repo { get; set; }

    private void DynamicImage_PreRender(object sender, EventArgs e)
    {
    }
}

Here's the updated InitializeHandler

public class Global : HttpApplication
{
    private static Container container;

    public static void InitializeHandler(IHttpHandler handler)
    {
        if (handler is Page)
        {
            Global.InitializePage((Page)handler);
        }
    }

    private static void InitializePage(Page page)
    {
        container.GetRegistration(page.GetType(), true).Registration
            .InitializeInstance(page);

        page.InitComplete += delegate { Global.InitializeControl(page); };
    }

    private static void InitializeControl(Control control)
    {
        if (control is UserControl)
        {
            container.GetRegistration(control.GetType(), true).Registration
                .InitializeInstance(control);
        }
        foreach (Control child in control.Controls)
        {
            Global.InitializeControl(child);
        }
    }

And the 2 other changes from the documentation. Be sure to call RegisterWebPagesAndControls in your bootstrapper

private static void RegisterWebPagesAndControls(Container container)
{
    var pageTypes =
        from assembly in BuildManager.GetReferencedAssemblies().Cast<Assembly>()
        where !assembly.IsDynamic
        where !assembly.GlobalAssemblyCache
        from type in assembly.GetExportedTypes()
        where type.IsSubclassOf(typeof(Page)) || type.IsSubclassOf(typeof(UserControl))
        where !type.IsAbstract && !type.IsGenericType
        select type;

    pageTypes.ToList().ForEach(container.Register);
}

class ImportAttributePropertySelectionBehavior : IPropertySelectionBehavior
{
    public bool SelectProperty(Type serviceType, PropertyInfo propertyInfo)
    {
        // Makes use of the System.ComponentModel.Composition assembly
        return (typeof(Page).IsAssignableFrom(serviceType) ||
            typeof(UserControl).IsAssignableFrom(serviceType)) &&
            propertyInfo.GetCustomAttributes<ImportAttribute>().Any();
    }
}
like image 99
qujck Avatar answered Feb 25 '26 06:02

qujck



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!