Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 198729
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T16:57:45+00:00 2026-05-11T16:57:45+00:00

Context: .NET 3.5, VS2008. I’m not sure about the title of this question, so

  • 0

Context: .NET 3.5, VS2008. I’m not sure about the title of this question, so feel free to comment about the title, too 🙂

Here’s the scenario: I have several classes, say Foo and Bar, all of them implement the following interface:

public interface IStartable
{
    void Start();
    void Stop();
}

And now I’d like to have a container class, which gets an IEnumerable<IStartable> as an argument in its constructor. This class, in turn, should also implement the IStartable interface:

public class StartableGroup : IStartable // this is the container class
{
    private readonly IEnumerable<IStartable> startables;

    public StartableGroup(IEnumerable<IStartable> startables)
    {
        this.startables = startables;
    }

    public void Start()
    {
        foreach (var startable in startables)
        {
            startable.Start();
        }
    }

    public void Stop()
    {
        foreach (var startable in startables)
        {
            startable.Stop();
        }
    }
}

So my question is: how can I do it without manually writing the code, and without code generation? In other words, I’d like to have somethig like the following.

var arr = new IStartable[] { new Foo(), new Bar("wow") };
var mygroup = GroupGenerator<IStartable>.Create(arr);
mygroup.Start(); // --> calls Foo's Start and Bar's Start

Constraints:

  • No code generation (that is, no real textual code at compile time)
  • The interface has only void methods, with or without arguments

Motivation:

  • I have a pretty large application, with a lot of plugins of various interfaces. Manually writing a “group container” class for each interface “overloads” the project with classes
  • Manually writing the code is error prone
  • Any additions or signature updates to the IStartable interface will lead to (manual) changes in the “group container” class
  • Learning

I understand that I have to use reflection here, but I’d rather use a robust framework (like Castle’s DynamicProxy or RunSharp) to do the wiring for me.

Any thoughts?

  • 1 1 Answer
  • 3 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-11T16:57:45+00:00Added an answer on May 11, 2026 at 4:57 pm

    This isn’t pretty, but it seems to work:

    public static class GroupGenerator
    {
        public static T Create<T>(IEnumerable<T> items) where T : class
        {
            return (T)Activator.CreateInstance(Cache<T>.Type, items);
        }
        private static class Cache<T> where T : class
        {
            internal static readonly Type Type;
            static Cache()
            {
                if (!typeof(T).IsInterface)
                {
                    throw new InvalidOperationException(typeof(T).Name
                        + " is not an interface");
                }
                AssemblyName an = new AssemblyName("tmp_" + typeof(T).Name);
                var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(
                    an, AssemblyBuilderAccess.RunAndSave);
                string moduleName = Path.ChangeExtension(an.Name,"dll");
                var module = asm.DefineDynamicModule(moduleName, false);
                string ns = typeof(T).Namespace;
                if (!string.IsNullOrEmpty(ns)) ns += ".";
                var type = module.DefineType(ns + "grp_" + typeof(T).Name,
                    TypeAttributes.Class | TypeAttributes.AnsiClass |
                    TypeAttributes.Sealed | TypeAttributes.NotPublic);
                type.AddInterfaceImplementation(typeof(T));
    
                var fld = type.DefineField("items", typeof(IEnumerable<T>),
                    FieldAttributes.Private);
                var ctor = type.DefineConstructor(MethodAttributes.Public,
                    CallingConventions.HasThis, new Type[] { fld.FieldType });
                var il = ctor.GetILGenerator();
                // store the items
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Stfld, fld);
                il.Emit(OpCodes.Ret);
    
                foreach (var method in typeof(T).GetMethods())
                {
                    var args = method.GetParameters();
                    var methodImpl = type.DefineMethod(method.Name,
                        MethodAttributes.Private | MethodAttributes.Virtual,
                        method.ReturnType,
                        Array.ConvertAll(args, arg => arg.ParameterType));
                    type.DefineMethodOverride(methodImpl, method);
                    il = methodImpl.GetILGenerator();
                    if (method.ReturnType != typeof(void))
                    {
                        il.Emit(OpCodes.Ldstr,
                            "Methods with return values are not supported");
                        il.Emit(OpCodes.Newobj, typeof(NotSupportedException)
                            .GetConstructor(new Type[] {typeof(string)}));
                        il.Emit(OpCodes.Throw);
                        continue;
                    }
    
                    // get the iterator
                    var iter = il.DeclareLocal(typeof(IEnumerator<T>));
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, fld);
                    il.EmitCall(OpCodes.Callvirt, typeof(IEnumerable<T>)
                        .GetMethod("GetEnumerator"), null);
                    il.Emit(OpCodes.Stloc, iter);
                    Label tryFinally = il.BeginExceptionBlock();
    
                    // jump to "progress the iterator"
                    Label loop = il.DefineLabel();
                    il.Emit(OpCodes.Br_S, loop);
    
                    // process each item (invoke the paired method)
                    Label doItem = il.DefineLabel();
                    il.MarkLabel(doItem);
                    il.Emit(OpCodes.Ldloc, iter);
                    il.EmitCall(OpCodes.Callvirt, typeof(IEnumerator<T>)
                        .GetProperty("Current").GetGetMethod(), null);
                    for (int i = 0; i < args.Length; i++)
                    { // load the arguments
                        switch (i)
                        {
                            case 0: il.Emit(OpCodes.Ldarg_1); break;
                            case 1: il.Emit(OpCodes.Ldarg_2); break;
                            case 2: il.Emit(OpCodes.Ldarg_3); break;
                            default:
                                il.Emit(i < 255 ? OpCodes.Ldarg_S
                                    : OpCodes.Ldarg, i + 1);
                                break;
                        }
                    }
                    il.EmitCall(OpCodes.Callvirt, method, null);
    
                    // progress the iterator
                    il.MarkLabel(loop);
                    il.Emit(OpCodes.Ldloc, iter);
                    il.EmitCall(OpCodes.Callvirt, typeof(IEnumerator)
                        .GetMethod("MoveNext"), null);
                    il.Emit(OpCodes.Brtrue_S, doItem);
                    il.Emit(OpCodes.Leave_S, tryFinally);
    
                    // dispose iterator
                    il.BeginFinallyBlock();
                    Label endFinally = il.DefineLabel();
                    il.Emit(OpCodes.Ldloc, iter);
                    il.Emit(OpCodes.Brfalse_S, endFinally);
                    il.Emit(OpCodes.Ldloc, iter);
                    il.EmitCall(OpCodes.Callvirt, typeof(IDisposable)
                        .GetMethod("Dispose"), null);
                    il.MarkLabel(endFinally);
                    il.EndExceptionBlock();
                    il.Emit(OpCodes.Ret);
                }
                Cache<T>.Type = type.CreateType();
    #if DEBUG       // for inspection purposes...
                asm.Save(moduleName);
    #endif
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Recently I've started learning about Contexts in .NET (context-bound, context-agile, message sinks, etc.). Several
Context I want to use JavaFx with clojure. I am aware of http://nailthatbug.net/2011/06/clojure-javafx-2-0-simple-app/ Question:
I am using VS2008 for ASP.NET apps. My Solution Explorer has hierarchy like this:
Context: .Net, C# I want to print a complex number made from two doubles.
Context: ASP.NET MVC 2.0, C#, SQL Server 2008, IIS7 I have 'scheduledMeetings' table in
how to differentiate whether a managed library is running in the context of asp.net
Please explain impersonation for non-technical users.Then please explain it in the context of ASP.NET.
Context Language: C# Platform Version: Microsoft .Net Framework 4.0 Operating System: Windows 7 Professional
In vb.net (2008), I want to be able to control when a contextMenuStrip (context
My .ascx is into folder /cms/context/ , and it is called Test.ascx (on .NET

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.