Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. How to create method extensions but inject into them with IoC

How to create method extensions but inject into them with IoC

Scheduled Pinned Locked Moved C#
helpdatabaseperformancetutorialquestion
6 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    Gizz
    wrote on last edited by
    #1

    Hi all Here is my conundrum: I have a helper class/function that says if a date is a working day. It does this by reading in the holidays from the database and checking the date against weekends, and then holidays. It holds the holidays in a dictionary keyed by date for quick lookup and caching. It is passed an interface to a holiday repository in the ctor and everything is injected via Castle Windsor ctor injection from a root entity. It needs to be an in-memory cache and readily accessible as it is used a lot. So far so good. How would you go about making this a static extension method to DateTime? (Since you can’t inject to static classes…) The basic problem is, can you pass stuff into an extension method using CW? Or am I stuck with injection all the way and no statics, and therefore no extension methods? I came up with a hack that uses a collection in the static helper class, and gets set with the holiday cache beforehand, but it just seemed a bit klunky... Thanks in advance for any ideas...

    B 1 Reply Last reply
    0
    • G Gizz

      Hi all Here is my conundrum: I have a helper class/function that says if a date is a working day. It does this by reading in the holidays from the database and checking the date against weekends, and then holidays. It holds the holidays in a dictionary keyed by date for quick lookup and caching. It is passed an interface to a holiday repository in the ctor and everything is injected via Castle Windsor ctor injection from a root entity. It needs to be an in-memory cache and readily accessible as it is used a lot. So far so good. How would you go about making this a static extension method to DateTime? (Since you can’t inject to static classes…) The basic problem is, can you pass stuff into an extension method using CW? Or am I stuck with injection all the way and no statics, and therefore no extension methods? I came up with a hack that uses a collection in the static helper class, and gets set with the holiday cache beforehand, but it just seemed a bit klunky... Thanks in advance for any ideas...

      B Offline
      B Offline
      BobJanova
      wrote on last edited by
      #2

      Uh, am I missing something obvious?

      public static bool IsWorkingDay(this DateTime dt){
      // whatever
      return false; // I'm on CP, of course I'm not working :)
      }

      permits

      bool shouldIBeWorking = DateTime.Now.IsWorkingDay();

      (Is it possible to have extension properties? I don't think so, right?) This is completely independent of dependency injection and as long as the extension method is visible in the place you're trying to use it (i.e. in the same assembly, or a referenced assembly, and you have a using statement for the class that defines it) it should work anywhere.

      G 1 Reply Last reply
      0
      • B BobJanova

        Uh, am I missing something obvious?

        public static bool IsWorkingDay(this DateTime dt){
        // whatever
        return false; // I'm on CP, of course I'm not working :)
        }

        permits

        bool shouldIBeWorking = DateTime.Now.IsWorkingDay();

        (Is it possible to have extension properties? I don't think so, right?) This is completely independent of dependency injection and as long as the extension method is visible in the place you're trying to use it (i.e. in the same assembly, or a referenced assembly, and you have a using statement for the class that defines it) it should work anywhere.

        G Offline
        G Offline
        Gizz
        wrote on last edited by
        #3

        I'll try again with an example: Here is the current naive implementation:

        public static class DateExtension
        {
            static readonly Dictionary<DateTime, Holiday> Dict;
            static DateExtension()
            {
                Dict = new Dictionary<DateTime, Holiday>();
            }
        
            public static void SetHoliday(Holiday holidayToAdd)
            {
                Dict.Add(holidayToAdd.Date, holidayToAdd);
            }
        
            public static bool IsWorkingDay(this DateTime dateToCheck)
            {
                if (dateToCheck.DayOfWeek == DayOfWeek.Saturday ||
                    dateToCheck.DayOfWeek == DayOfWeek.Sunday)
                {
                    return false;
                }
        
                return !Dict.ContainsKey(dateToCheck);
            }
        }
        
        /// <summary>
        /// This is the Holiday entity pulled from DB using NH or similar...
        /// </summary>
        public class Holiday
        {
            public virtual DateTime Date { get; set; }
            public virtual string Description { get; set; }
        }
        

        To use this, you have to stuff the DateExtension with the holidays first

        Holiday hol = new Holiday {Date = new DateTime(2012, 1, 2), Description = "NYD 2012"};
        DateExtension.SetHoliday(hol);

        So you would use it like this:

        DateTime dt = new DateTime(2012, 1, 2);

        Debug.Assert(!dt.IsWorkingDay());
        dt = dt.AddDays(1);
        Debug.Assert(dt.IsWorkingDay());

        Now, the question is about, how can I nicely get CW to instantiate the holidays into the static extension, without doing something like this:

        var holRep = _container.Resolve<IHolidayRepository>();
        DateExtension.SetAllHolidays(holRep.All());

        In other words, can anyone think of a way to do this automatically within CW by simply registering the static class DateExtension in CW and have it inject the repository for me? Thx

        B 1 Reply Last reply
        0
        • G Gizz

          I'll try again with an example: Here is the current naive implementation:

          public static class DateExtension
          {
              static readonly Dictionary<DateTime, Holiday> Dict;
              static DateExtension()
              {
                  Dict = new Dictionary<DateTime, Holiday>();
              }
          
              public static void SetHoliday(Holiday holidayToAdd)
              {
                  Dict.Add(holidayToAdd.Date, holidayToAdd);
              }
          
              public static bool IsWorkingDay(this DateTime dateToCheck)
              {
                  if (dateToCheck.DayOfWeek == DayOfWeek.Saturday ||
                      dateToCheck.DayOfWeek == DayOfWeek.Sunday)
                  {
                      return false;
                  }
          
                  return !Dict.ContainsKey(dateToCheck);
              }
          }
          
          /// <summary>
          /// This is the Holiday entity pulled from DB using NH or similar...
          /// </summary>
          public class Holiday
          {
              public virtual DateTime Date { get; set; }
              public virtual string Description { get; set; }
          }
          

          To use this, you have to stuff the DateExtension with the holidays first

          Holiday hol = new Holiday {Date = new DateTime(2012, 1, 2), Description = "NYD 2012"};
          DateExtension.SetHoliday(hol);

          So you would use it like this:

          DateTime dt = new DateTime(2012, 1, 2);

          Debug.Assert(!dt.IsWorkingDay());
          dt = dt.AddDays(1);
          Debug.Assert(dt.IsWorkingDay());

          Now, the question is about, how can I nicely get CW to instantiate the holidays into the static extension, without doing something like this:

          var holRep = _container.Resolve<IHolidayRepository>();
          DateExtension.SetAllHolidays(holRep.All());

          In other words, can anyone think of a way to do this automatically within CW by simply registering the static class DateExtension in CW and have it inject the repository for me? Thx

          B Offline
          B Offline
          BobJanova
          wrote on last edited by
          #4

          Ah, okay, now I see the problem. The easiest way is to register in reverse, i.e. pass a container to the extension class:

          static class DateExtensions {
          static IUnityContainer container;
          static HolidayHandler handler;

          public static void RegisterHolidayHandler(IUnityContainer container){
          container.Register<HolidayHandler, HolidayHandler>();
          this.container = container;
          }

          public static bool IsHoliday(){
          if(handler == null) handler = container.Resolve<HolidayHandler>();
          // etc
          }

          class HolidayHandler {
          internal List<Holidays> holidays;
          public HolidayHandler(EntityContext context){
          holidays = context.GetHolidays();
          // or however your lookup classes work
          // EntityContext can be got from IoC
          }
          }
          }

          If you want some syntactic tidyness then of course RegisterHolidayHandler can itself be an extension method. If you don't want to have a dependency on the dependency injection framework here (and I don't think you do, really), you need to give the extension class a property (of type IHolidayHandler or something) and explicitly assign an instance of a subclass which is populated by IoC. This is essentially 'loading the holidays' but with the mechanics of it abstracted and hidden away. That is pretty much what you say you don't want to do. I can't think of a clever way without having to do, at least,

          DateExtensions.HolidayRepository = _container.Resolve<IHolidayRepository>();

          G 1 Reply Last reply
          0
          • B BobJanova

            Ah, okay, now I see the problem. The easiest way is to register in reverse, i.e. pass a container to the extension class:

            static class DateExtensions {
            static IUnityContainer container;
            static HolidayHandler handler;

            public static void RegisterHolidayHandler(IUnityContainer container){
            container.Register<HolidayHandler, HolidayHandler>();
            this.container = container;
            }

            public static bool IsHoliday(){
            if(handler == null) handler = container.Resolve<HolidayHandler>();
            // etc
            }

            class HolidayHandler {
            internal List<Holidays> holidays;
            public HolidayHandler(EntityContext context){
            holidays = context.GetHolidays();
            // or however your lookup classes work
            // EntityContext can be got from IoC
            }
            }
            }

            If you want some syntactic tidyness then of course RegisterHolidayHandler can itself be an extension method. If you don't want to have a dependency on the dependency injection framework here (and I don't think you do, really), you need to give the extension class a property (of type IHolidayHandler or something) and explicitly assign an instance of a subclass which is populated by IoC. This is essentially 'loading the holidays' but with the mechanics of it abstracted and hidden away. That is pretty much what you say you don't want to do. I can't think of a clever way without having to do, at least,

            DateExtensions.HolidayRepository = _container.Resolve<IHolidayRepository>();

            G Offline
            G Offline
            Gizz
            wrote on last edited by
            #5

            Thanks BobJanova. Isn't passing around a reference to the container an anti-pattern? Anyway, I'm specifically trying to avoid directly calling resolve against any repositories, as I want all the plumbing to be automatic through ctor/field injection. Which you can't (apparently) do with statics, and CW. Hmmm.... Rgds

            B 1 Reply Last reply
            0
            • G Gizz

              Thanks BobJanova. Isn't passing around a reference to the container an anti-pattern? Anyway, I'm specifically trying to avoid directly calling resolve against any repositories, as I want all the plumbing to be automatic through ctor/field injection. Which you can't (apparently) do with statics, and CW. Hmmm.... Rgds

              B Offline
              B Offline
              BobJanova
              wrote on last edited by
              #6

              Yes, I suspect it is, which is why I suggest doing it the other way. I'm pretty sure you can't do property/field injection on a static because there is no point at which an instance of it is created by the container and passed to something else. Obviously you can't do constructor parameter injection. Personally I don't like dependency injection much and consider the whole field something of an anti-pattern so perhaps I'm not the ideal person to be trying to help you ;)

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups