作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当 Fitnesse 实例化一个夹具时,它会寻找一个默认的公共(public)构造函数。
但是,我想在构造函数中注入(inject)我想在夹具中使用的任何应用程序服务。
即我想这样写我的装置......
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.xml 中注册...
<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, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, 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, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, 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 代码...
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 的创建操作。它将实现这个接口(interface):
public interface CreateOperator<T> {
bool CanCreate(NameMatcher memberName, Tree<T> parameters);
TypedValue Create(NameMatcher memberName, Tree<T> parameters);
}
然后你告诉 fitSharp 在套件配置文件中使用这个类:
<suiteConfig>
<Fit.Operators>
<Add>My.Create.Operator</Add>
</Fit.Operators>
...
</suiteConfig>
作为陈述点,这里有一个非常简单的创建运算符。您将对其进行修改以进行 AutoFac 注入(inject)。
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, 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) {
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, 0, 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);
}
}
}
关于c# - 如何将 Fitnesse 与 Autofac/IOC 集成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26176050/
我是一名优秀的程序员,十分优秀!