【问题标题】:Custom Instance Provider doesn't trigger in Xamarin.Forms App自定义实例提供程序不会在 Xamarin.Forms 应用程序中触发
【发布时间】:2019-09-01 23:29:28
【问题描述】:

我已阅读“Mastering Ninject for Dependency Injection”一书,并进行了 Telecom 练习,它教您在 2 个或更多类共享相同接口的情况下使用自定义实例提供程序。

我尝试将相同的概念应用于 DesignTime 数据和运行时,如果我不使用工厂或约定,我的应用程序可以正常工作,但是,一旦我尝试使用自定义实例提供程序,代码似乎很好,但是当它到达工厂实现它不会触发我的实例提供程序来获取运行时或设计时数据的正确实现。

这是我的忍者模块:

public class WhyMvvmModule : NinjectModule
{
    public override void Load()
    {
        Bind<IFriendServiceFactory>().ToFactory(() => new NameAttributeInstanceProvider());
        Bind<IDialogService>().To<DialogService>();
        Bind<INavigationServiceExtension>().To<NavigationService>();
        Bind<IFriendService>().To<FriendService>().NamedLikeFactoryMethod((IFriendServiceFactory f) => f.GetFriendService());
        Bind<IFriendService>().To<DesignFriendService>().NamedLikeFactoryMethod((IFriendServiceFactory f) => f.GetDesignFriendService());
        Bind<IFileStorageService>().To<FileStorageService>();
    }
}

这是共享界面:

public interface IFriendService
{
    Task<IEnumerable<Friend>> Refresh();
    Task<string> Save(Friend updatedFriend);
}

这是我的带有 BindingName 属性的工厂接口,用于选择要应用的服务:

public interface IFriendServiceFactory
{
    [BindingName("DesignFriendService")]
    IFriendService GetDesignFriendService();
    [BindingName("FriendService")]
    IFriendService GetFriendService();
}

这些是服务实现:

public class DesignFriendService : IFriendService
{
    public Task<IEnumerable<Friend>> Refresh()
    {
        var result = new List<Friend>();
        for (int i = 0; i < 10; i++)
        {
            result.Add(new Friend { Id = i, FirstName = $"First Name {i}", LastName = $"Last Name {i}", PictureUrl = "LinkedInOriginalLogo256x256.png" });
        }
        return Task.FromResult<IEnumerable<Friend>>(result);
    }

    public Task<string> Save(Friend updatedFriend)
    {
        throw new NotImplementedException();
    }
}

和运行时服务:

public class FriendService : IFriendService
{
    public async Task<IEnumerable<Friend>> Refresh()
    {
        var result = await App.FriendRepo.GetAllFriendsAsync();

        return result.Data;
    }

    public async Task<string> Save(Friend updatedFriend)
    {
        string result = string.Empty;
        result = (await App.FriendRepo.UpdateFriendAsync(updatedFriend)).ToString();

        return result;
    }
}

这是我的自定义实例提供程序:

public class NameAttributeInstanceProvider : StandardInstanceProvider
{
    protected override string GetName(MethodInfo methodInfo, object[] arguments)
    {
        if (methodInfo.GetCustomAttributes(typeof(BindingNameAttribute), true)
            .FirstOrDefault() is BindingNameAttribute nameAttribute)
            return nameAttribute.Name;
        return base.GetName(methodInfo, arguments);
    }
}

这是我的属性,自定义实例提供程序将获取应用于 IFriendServiceFactory 的属性或类的名称:

public class BindingNameAttribute : Attribute
{
    public BindingNameAttribute(string name)
    {
        Name = name;
    }

    public string Name { get; set; }
}

最后,这是我运行应用程序时代码中断的地方。它甚至没有运行,它在我的 ViewModel 上调用 SwitchFriendService 类的 Refresh 方法向我抛出了一个异常:

ViewModel 方法:

async Task Refresh()
{
    Friends.Clear();

    var friends = await _dataService.Refresh();

    foreach (var friend in friends)
    {
        Friends.Add(friend);
    }
}

public MainViewModel(Abstractions.IDialogService dialogService, INavigationServiceExtension navigationService)
{
    //_dataService = ServiceLocator.Current.GetInstance<SwitchFriendService>();
    _dataService = ViewModelLocator.Instance.NinjectContainer.Get<SwitchFriendService>();
    _dialogService = dialogService;
    _navigationService = navigationService;
    Friends = new ObservableCollection<Friend>();

    #if DEBUG
        if (DesignMode.IsDesignModeEnabled)
        {
    #pragma warning disable
            Refresh();
    #pragma warning restore
        }
    #endif
    }

还有 SwitchFriendService:

public class SwitchFriendService
{
    readonly IFriendServiceFactory _switchFriendServiceFactory;
    public SwitchFriendService(IFriendServiceFactory switchFriendServiceFactory)
    {
        _switchFriendServiceFactory = switchFriendServiceFactory;
    }

    public async Task<IEnumerable<Friend>> Refresh()
    {
        IFriendService friendService;
        if(DesignMode.IsDesignModeEnabled)
        {
            friendService = _switchFriendServiceFactory.GetDesignFriendService();
        }
        else
        {
            friendService = _switchFriendServiceFactory.GetFriendService();
        }
        return await friendService.Refresh();
    }

    public async Task<string> Save(Friend updatedFriend)
    {
        IFriendService friendService;
        if (DesignMode.IsDesignModeEnabled)
        {
            friendService = _switchFriendServiceFactory.GetDesignFriendService();
        }
        else
        {
            friendService = _switchFriendServiceFactory.GetFriendService();
        }

        return await friendService.Save(updatedFriend);
    }
}

现在我将通过屏幕截图向您展示异常,因为我不明白为什么它没有加载正确的实现,概念和设备实际上与本书相同。

这是我从 Ninject 收到的消息:

未处理的异常: System.NotImplementedException:这是 DynamicProxy2 错误:没有为没有目标的方法“WhyMvvm.MvvmLightIoc.Abstractions.IFriendService GetFriendService()”指定拦截器。当调用没有目标的方法时,没有“继续”的实现,拦截器有责任模仿实现(设置返回值、输出参数等)

线程完成:#13

但我没有使用拦截器。我应该使用自定义提供程序。

有人可以帮忙完成这项工作吗,请。为了将其应用于 xamarin.forms。

在控制台版本中它工作正常。

希望有人能告诉我我错过了什么?

【问题讨论】:

    标签: c# xamarin xamarin.forms ninject ninject-extensions


    【解决方案1】:

    我能够解决它,事实证明可以通过手动加载 Ninject.Extensions.Factory 来纠正异常,并且可以通过首先添加 using 语句来实现

    使用 Ninject.Extensions.Factory;

    在我的情况下,我加载内核的位置是在我的 ViewModelLocator 中,因此我没有像我在问题中展示的那样声明我的标准内核,我必须像这样向内核添加一个 FuncModule:

    var settings = new NinjectSettings() { LoadExtensions = false };
    
    NinjectContainer = new StandardKernel(settings, new WhyMvvmModule(), new FuncModule());
    

    第二行代码使 InstanceProvider 工作正常!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-27
      • 1970-01-01
      • 1970-01-01
      • 2013-10-29
      相关资源
      最近更新 更多