我有两个实体基类:
public abstract class EntityBase { }
public abstract class ClientSpecificEntityBase : EntityBase
和两类实体:
public class Thing : EntityBase { }
public class ClientSpecificThing : ClientSpecificEntityBase { }
和两种类型的服务,它们都实现IService<T>
ServiceBase<T> : Service<T> where T : EntityBase
ClientSpecificServiceBase<T> : ServiceBase<T> where T : ClientSpecificEntityBase
我正在使用以下代码配置StructureMap:
_.For(typeof(IService<>)).Use(typeof(ServiceBase<>));
_.For<IService<ClientSpecificEntityBase>>().Use<ClientSpecificServiceBase<ClientSpecificEntityBase>>();
但每次我尝试访问IService<ClientSpecificThing>
:
public ClientSpecificThingController(IService<ClientSpecificThing> service)
我收到ServiceBase<ClientSpecificThing>
而不是ClientSpecificServiceBase<ClientSpecificThing>
有没有办法让StructureMap在映射ClientSpecificServiceBase<T>
时包含派生类型?
答案 0 :(得分:1)
不,你不能做你想做的事。容器不会通过已注册的组件查看泛型类型的基类。
如果您删除第一个注册,只留下
,这一点就会变得更加明显using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foundation;
using UIKit;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using System.IO;
using WebKit;
[assembly: ExportRenderer(typeof(MyProject.HybridWebView), typeof(MyProject.iOS.HybridWebViewRenderer))]
namespace MyProject.iOS
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
const string JavaScriptFunction = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta); function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
WKUserContentController userController;
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
userController = new WKUserContentController();
var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript(script);
userController.AddScriptMessageHandler(this, "invokeAction");
var config = new WKWebViewConfiguration { UserContentController = userController };
var webView = new WKWebView(Frame, config);
SetNativeControl(webView);
webView.Opaque = false;
webView.BackgroundColor = UIColor.Clear;
webView.ScrollView.ScrollEnabled = false;
webView.ScrollView.Bounces = false;
}
if (e.OldElement != null)
{
userController.RemoveAllUserScripts();
userController.RemoveScriptMessageHandler("invokeAction");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
string fileName = Path.Combine(NSBundle.MainBundle.BundlePath, string.Format("Content/{0}", Element.Uri));
Control.LoadRequest(new NSUrlRequest(new NSUrl(fileName, false)));
}
}
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
Element.InvokeAction(message.Body.ToString());
}
}
}
现在,如果你打电话
_.For<IService<ClientSpecificEntityBase>>()
.Use<ClientSpecificServiceBase<ClientSpecificEntityBase>>();
您将获得例外:
StructureMap.StructureMapConfigurationException:没有注册默认实例,无法自动确定类型&#39; IService&#39;
因此,并不是说StructureMap在两个注册之间混淆并且返回错误的注册。当你注册时,它并没有意识到:
var resolved = container.GetInstance<IService<ClientSpecificThing>>();
它可以使用它来实现这一点,因为一个泛型类型继承自另一个。
IService<ClientSpecificEntityBase>