当fitnesse实例化一个fixture时,它会查找默认的公共构造函数.
但是,我想构造函数注入我想要在fixture中使用的任何应用程序服务.
即我想写这个夹具……
public class MyColumnFixture : ColumnFixture { private readonly Iapplicationservice _applicationservice; public ManualExitSetupFixture(Iapplicationservice applicationservice) { _applicationservice = applicationservice; } public void DoStuff(string arg1) { _applicationservice.DoStuff(arg1); } }
到目前为止,我设法提出的最好的方法是将容器暴露为单例(见下文).但必须有更好的方法. Autofac与我们使用的许多其他技术完美集成.
public class AutofacIntegration { private static IContainer _container; public static IContainer Container { get { if (_container == null) { var builder = new ContainerBuilder(); builder.RegisterModule<MyApplicationModule>(); _container = builder.Build(); } return _container; } } } public class MyColumnFixture : ColumnFixture { private readonly Iapplicationservice _applicationservice; public ManualExitSetupFixture() { _applicationservice = AutofacIntegration.Container.Resolve<Iapplicationservice>(); } public void DoStuff(string arg1) { _applicationservice.DoStuff(arg1); } }
编辑:包括更多细节,我试图在Mike的帮助下完成这项工作……
我创建了一个类,它是从fitsharp反编译的CreateDefault的反编译代码中复制粘贴的…
public class CreateDefault<T,P> : Operator<T,P>,CreateOperator<T> where P : class,Processor<T> { public bool CanCreate(NameMatcher memberName,Tree<T> parameters) { return true; } public TypedValue Create(NameMatcher memberName,Tree<T> parameters) { ... } }
<suiteConfig> <ApplicationUnderTest> <AddAssembly>..\..\Services\Win\MyProj.fitnesse\MyProj.fitnesse\bin\Debug\MyProj.fitnesse.dll</AddAssembly> </ApplicationUnderTest> <Fit.Operators> <Add>MyProj.fitnesse.CreateDefault`2</Add> </Fit.Operators> </suiteConfig>
…这会在尝试加载我的CreateDefault<,>时出现以下异常类.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> fitsharp.Machine.Exception.CreateException: Constructor with 0 parameter(s) Failed for type 'MyProj.fitnesse.CreateDefault`2'. ---> System.ArgumentException: Cannot create an instance of MyProj.fitnesse.CreateDefault`2[T,P] because Type.ContainsGenericParameters is true. at System.RuntimeType.CreateInstanceCheckThis() at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr,Binder binder,Object[] args,CultureInfo culture,Object[] activationAttributes,StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type,BindingFlags bindingAttr,Object[] activationAttributes) at System.Reflection.Assembly.CreateInstance(String typeName,Boolean ignoreCase,Object[] activationAttributes) at fitsharp.Machine.Engine.RuntimeType.CreateInstance() at fitsharp.Machine.Engine.CreateDefault`2.CreateWithoutParameters(RuntimeType runtimeType) --- End of inner exception stack trace --- at fitsharp.Machine.Engine.CreateDefault`2.CreateWithoutParameters(RuntimeType runtimeType) at fitsharp.Machine.Engine.CreateDefault`2.Create(NameMatcher memberName,Tree`1 parameters) --- End of inner exception stack trace --- at System.RuntimeMethodHandle.InvokeMethod(Object target,Object[] arguments,Signature sig,Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,Object[] parameters,Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,CultureInfo culture) at System.RuntimeType.InvokeMember(String name,BindingFlags bindingFlags,Object target,Object[] providedArgs,ParameterModifier[] modifiers,String[] namedParams) at fitsharp.Machine.Engine.MethodMember.TryInvoke(Object[] parameters) at fitsharp.Machine.Engine.ReflectionMember.Invoke(Object[] parameters) at fitsharp.Machine.Engine.ProcessorBase`2.Operate[O](Object[] parameters) at fitsharp.Machine.Engine.Operators`2.Add(String operatorName) --- End of inner exception stack trace --- at fitsharp.Machine.Engine.ProcessorExtension.InvokeWithThrow[T](Processor`1 processor,TypedValue instance,MemberName memberName,Tree`1 parameters) at fitsharp.Machine.Application.SuiteConfiguration.LoadNode(String typeName,XmlNode methodNode) at fitsharp.Machine.Application.SuiteConfiguration.LoadXml(String configurationXml) at fitsharp.Machine.Application.ArgumentParser.InvokeArgumentHandler(String switch,String argumentValue) at fitsharp.Machine.Application.ArgumentParser.Parse(IList`1 commandLineArguments) at fitsharp.Machine.Application.Shell.Run(IList`1 commandLineArguments)
编辑:非常感谢迈克,现在正在努力享受.
>定义自定义CreateOperator
>创建SuiteConfig.xml以指向dll并加载自定义create运算符
>启动跑步者时指定SuiteConfig
>注册灯具
我的CreateOperator代码……
public class AutofacCreateOperator : CellOperator,CreateOperator<Cell> { private static IContainer _container; public AutofacCreateOperator() { var builder = new ContainerBuilder(); builder.RegisterModule<fitnesseModule>(); _container = builder.Build(); } public bool CanCreate(NameMatcher memberName,Tree<Cell> parameters) { return _container.ComponentRegistry.IsRegistered(new TypedService(Type.GetType(memberName.MatchName))); } public TypedValue Create(NameMatcher memberName,Tree<Cell> parameters) { return new TypedValue(_container.Resolve(Type.GetType(memberName.MatchName))); } }
解决方法
这可以完成 – 您需要编写一个自定义类来处理fitsharp的创建操作.它将实现此接口:
public interface CreateOperator<T> { bool CanCreate(NameMatcher memberName,Tree<T> parameters); TypedValue Create(NameMatcher memberName,Tree<T> parameters); }
<suiteConfig> <Fit.Operators> <Add>My.Create.Operator</Add> </Fit.Operators> ... </suiteConfig>
作为一个说明点,这是一个非常简单的创建运算符.你可以修改它来进行AutoFac注入.
public class TestCreateOperator: CellOperator,CreateOperator<Cell> { public bool CanCreate(NameMatcher memberName,Tree<Cell> parameters) { return memberName.Matches("testname"); } public TypedValue Create(NameMatcher memberName,Tree<Cell> parameters) { return new TypedValue("mytestname"); } }
仅供参考,这是内置类,用于创建夹具.
public class CreateDefault<T,P>: Operator<T,CreateOperator<T> where P: class,Processor<T> { public bool CanCreate(NameMatcher memberName,Tree<T> parameters) { return true; } public TypedValue Create(NameMatcher memberName,Tree<T> parameters) { var runtimeType = Processor.ApplicationUnderTest.FindType(memberName); return parameters.Branches.Count == 0 ? CreateWithoutParameters(runtimeType) : CreateWithParameters(parameters,runtimeType); } static TypedValue CreateWithoutParameters(RuntimeType runtimeType) { try { return runtimeType.CreateInstance(); } catch (System.Exception e) { throw new CreateException(runtimeType.Type,e.InnerException ?? e); } } TypedValue CreateWithParameters(Tree<T> parameters,RuntimeType runtimeType) { RuntimeMember member = runtimeType.GetConstructor(parameters.Branches.Count); object[] parameterList = new ParameterList<T>(Processor).GetParameterList(TypedValue.Void,parameters,member); try { return member.Invoke(parameterList); } catch (System.Exception e) { throw new CreateException(runtimeType.Type,parameterList.Length,e.InnerException ?? e); } } }