StructureMap可以返回特殊情况吗?

时间:2011-08-11 07:00:58

标签: c# asp.net-mvc structuremap null-object-pattern

我想让StructureMap为某个实例返回一个名为“None”的Special Case

说我有这个类MyUser,它的作用域是HttpContext。我希望有一个嵌套的,可能的类None(即MyUser.None),当没有MyUser时,它会被HttpContext类型重新调整(例如,像在引导中一样) ,Application_Start()等。

这意味着某些调用可以检查特殊情况类型而不是null(更易读),如

if(value is MyUser.None)
  // do special case things
else
  // do normal case things

我需要什么SM配置来实现这一目标?我尝试了ConditionallyUse方法但没有取得多大成功。我一直在SM内部投掷NullReferenceExceptionS

2 个答案:

答案 0 :(得分:2)

这段代码应该可以工作(要测试,你可以用DateTime.Now.Millisecond % 2 == 0替换HttpContext.Current的检查,以便更容易地看到不同的行为):

class Program
{
    static void Main(string[] args)
    {
        ObjectFactory.Initialize(x =>
        {
            x.For<IUser>().ConditionallyUse(cond =>
            {
                cond.TheDefault.Is.Type<MyUser>();
                cond.If(ctx =>
                {
                    var hasContext = false;
                    try
                    {
                        hasContext = HttpContext.Current == null;
                    }catch
                    {
                        // HttpContext.Current sometimes throws when there isn't one
                    }
                    return hasContext;
                }).ThenIt.IsThis(new MyUser.None());
            });
        });

        var instance = ObjectFactory.GetInstance<IUser>();
        Console.WriteLine(instance.GetType());
    }

    public interface IUser{}
    public class MyUser : IUser { public class None : IUser {} }
}

由于ConditionallyUse() API有点奇怪,您可能只想使用Use()的{​​{1}}重载并使用Func<>自行进行条件检查言。

答案 1 :(得分:1)

原来我有基本的SM配置问题。

我仍在使用ConditionallyUse方法:

        For<User>().ConditionallyUse(config =>
            {
                config.If(ctx => ctx.GetInstance<HttpContextBase>().User == null)
                    .ThenIt.Is.Type<User.None>();
                config.TheDefault.Is.Type<User>();
            });

我必须对SM中的NullReferenceExceptionS更加小心 - 我的根本原因似乎是scoping issue ..特别是我想要访问一个HttpContext范围的实例测试。我现在正在使用HybridHttpOrThreadLocalScoped()配置,并且使用适当的TryGetInstance()代替GetInstance()更加谨慎。