2016-10-28 40 views
12

依存性注入に実装したいASP.NET CORE 1私はすべてが.Net CoreのDIについて知っています。例Startup.csの外部に依存関係注入を実装する

public void ConfigureServices(IServiceCollection services) 
    { 
     // Add application services. 
    services.AddTransient<IDateTime, SystemDateTime>(); 
    } 

しかしに関しては、20の以上のエンティティとサービスを持っているビッグプロジェクトのために、それはとても難しいとConfigureServices内のこれらのコードの行のすべてを書いて読めないです。私は知りたいです。これはStartup.csの外部で依存性注入を実装してサービスに追加できるかどうかです。

お返事ありがとうございます。

+0

私は拡張メソッドを知っていますが、拡張メソッドごとに1行のコードでたくさんのものを追加するIServiceCollectionの拡張メソッドを書くことができます –

+0

私は拡張メソッドを知っています。しかし、例えばあなたは答えを書くことができますか? –

+0

登録グループに対して「抽出メソッド」リファクタリングを適用するとどうなりますか?後でこれらのメソッドを他のクラスに移動することもできます。 – Steven

答えて

8

あなたは、例えばStartup.cs

内のコードの1行にサービス登録の多くをカプセル化するIServiceCollectionの拡張メソッドを書くことができ、ここで私のプロジェクトからのものです:

using cloudscribe.Core.Models; 
using cloudscribe.Core.Models.Setup; 
using cloudscribe.Core.Web; 
using cloudscribe.Core.Web.Components; 
using cloudscribe.Core.Web.Components.Editor; 
using cloudscribe.Core.Web.Components.Messaging; 
using cloudscribe.Core.Web.Navigation; 
using cloudscribe.Web.Common.Razor; 
using cloudscribe.Web.Navigation; 
using cloudscribe.Web.Navigation.Caching; 
using Microsoft.AspNetCore.Http; 
using Microsoft.AspNetCore.Mvc.Razor; 
using Microsoft.Extensions.Configuration; 
using Microsoft.Extensions.DependencyInjection.Extensions; 
using Microsoft.Extensions.FileProviders; 
using Microsoft.Extensions.Options; 
using System.Reflection; 
using Microsoft.AspNetCore.Authorization; 

namespace Microsoft.Extensions.DependencyInjection 
{ 
    public static class StartupExtensions 
    { 
     public static IServiceCollection AddCloudscribeCore(this IServiceCollection services, IConfigurationRoot configuration) 
     { 
      services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
      services.Configure<MultiTenantOptions>(configuration.GetSection("MultiTenantOptions")); 
      services.Configure<SiteConfigOptions>(configuration.GetSection("SiteConfigOptions")); 
      services.Configure<UIOptions>(configuration.GetSection("UIOptions")); 
      services.Configure<CkeditorOptions>(configuration.GetSection("CkeditorOptions")); 
      services.Configure<CachingSiteResolverOptions>(configuration.GetSection("CachingSiteResolverOptions")); 
      services.AddMultitenancy<SiteContext, CachingSiteResolver>(); 
      services.AddScoped<CacheHelper, CacheHelper>(); 
      services.AddScoped<SiteManager, SiteManager>(); 
      services.AddScoped<GeoDataManager, GeoDataManager>(); 
      services.AddScoped<SystemInfoManager, SystemInfoManager>(); 
      services.AddScoped<IpAddressTracker, IpAddressTracker>(); 
      services.AddScoped<SiteDataProtector>(); 
      services.AddCloudscribeCommmon(); 
      services.AddScoped<ITimeZoneIdResolver, RequestTimeZoneIdResolver>(); 
      services.AddCloudscribePagination(); 
      services.AddScoped<IVersionProviderFactory, VersionProviderFactory>(); 
      services.AddScoped<IVersionProvider, CloudscribeCoreVersionProvider>(); 
      services.AddTransient<ISiteMessageEmailSender, SiteEmailMessageSender>(); 
      services.AddTransient<ISmsSender, SiteSmsSender>(); 
      services.AddSingleton<IThemeListBuilder, SiteThemeListBuilder>(); 
      services.TryAddScoped<ViewRenderer, ViewRenderer>(); 
      services.AddSingleton<IOptions<NavigationOptions>, SiteNavigationOptionsResolver>(); 
      services.AddScoped<ITreeCacheKeyResolver, SiteNavigationCacheKeyResolver>(); 
      services.AddScoped<INodeUrlPrefixProvider, FolderTenantNodeUrlPrefixProvider>(); 
      services.AddCloudscribeNavigation(configuration); 

      services.AddCloudscribeIdentity(); 

      return services; 
     } 


    } 
} 

とスタートアップで.cs私はコードの1行でそのメソッドを呼び出します

services.AddCloudscribeCore(Configuration); 
+2

こんにちは再びジョー..私たちはもう一度質問します...これは1つのアプローチであり、有効ですが、多くのメンテナンスが必要です。個人的に私はアセンブリスキャンを使用します(私の答えに概説されているように)。 – dmcquiggin

4

いくつかのアプローチがありますが、いくつかは単純にクラス間を移動するコードですs;

1.か「の問題を移動」:下記の2番目のオプションとして、私が説明するように、私はあなたがAssembly Scanning検討し提案する拡張メソッド

初期オプションは、サービスの設定にextension methodsを使用することです。ここ

here見出すことができるASP.Net MVC Bolierplateテンプレートから採取した1つの延長方法、に複数のサービスreigstrationsをラップ一例である。

public static IServiceCollection AddCustomServices(this IServiceCollection services) 
    { 
     services.AddScoped<IBrowserConfigService, BrowserConfigService>(); 
     services.AddScoped<IManifestService, ManifestService>(); 
     services.AddScoped<IRobotsService, RobotsService>(); 
     services.AddScoped<ISitemapService, SitemapService>(); 
     services.AddScoped<ISitemapPingerService, SitemapPingerService>(); 

     // Add your own custom services here e.g. 

     // Singleton - Only one instance is ever created and returned. 
     services.AddSingleton<IExampleService, ExampleService>(); 

     // Scoped - A new instance is created and returned for each request/response cycle. 
     services.AddScoped<IExampleService, ExampleService>(); 

     // Transient - A new instance is created and returned each time. 
     services.AddTransient<IExampleService, ExampleService>(); 

     return services; 
    } 

これはConfigureServices内で呼び出すことができます。

services.AddCustomServices(); 

注:特定の構成(たとえば、サービスに複数のオプションを渡す必要がある場合など)では、これはビルダーパターンとして役立ちます)、ハンドコーディングで複数のサービスを登録しなければならないという問題を解決することはできません。基本的には同じコードを別のクラスファイルに書くことと変わりはなく、依然として手動によるメンテナンスが必要です。

2.「問題を解決する」:ASSEMBLYのSCANNING

は、「ベストプラクティス」オプションは自動的にImplemented Interfacesに基づいて部品を検索し、登録するために使用されているAssembly Scanningです。以下Autofac例である:

var assembly= Assembly.GetExecutingAssembly(); 

builder.RegisterAssemblyTypes(assembly) 
     .Where(t => t.Name.EndsWith("Repository")) 
     .AsImplementedInterfaces(); 

寿命(または範囲)を処理するための1つのトリック登録、例えばIScopedServiceため、マーカーインターフェース(空のインタフェース)を使用して、スキャン・サービスを登録するためにそれを使用することです適切な生涯でこれは複数のサービスを登録するための最も摩擦の少ない手法であり、自動であり、したがって「ゼロ保守」です。

:組み込みのASP.Net Core DI実装では、Assembly Scanningはサポートされていません。

概要
var collection = new ServiceCollection(); 

collection.Scan(scan => scan 
    .FromAssemblyOf<ITransientService>() 
     .AddClasses(classes => classes.AssignableTo<ITransientService>()) 
      .AsImplementedInterfaces() 
      .WithTransientLifetime() 
     .AddClasses(classes => classes.AssignableTo<IScopedService>()) 
      .As<IScopedService>() 
      .WithScopedLifetime()); 

Extension Methods(該当する場合)との組み合わせで

Assembly Scanningは、保存されますが、GitHubの(およびNuget)のScrutorプロジェクトは、この機能を追加し、へのサービスおよびType登録を凝縮しますかなりの量のメンテナンスを行い、アプリケーションの起動時に一度実行され、その後キャッシュされます。コードサービス登録を手渡す必要がなくなります。

public static void AddScopedFromAssembly(this IServiceCollection services, Assembly assembly) 
    { 
     var allServices = assembly.GetTypes().Where(p => 
      p.GetTypeInfo().IsClass && 
      !p.GetTypeInfo().IsAbstract); 
     foreach (var type in allServices) 
     { 
      var allInterfaces = type.GetInterfaces(); 
      var mainInterfaces = allInterfaces.Except 
        (allInterfaces.SelectMany(t => t.GetInterfaces())); 
      foreach (var itype in mainInterfaces) 
      { 
       services.AddScoped(itype, type); // if you want you can pass lifetime as a parameter 
      } 
     } 
    } 

と使用方法:

2

あなたが一括登録のための拡張メソッド書くことができます

services.AddScopedFromAssembly(assembly); 
0

を私は最近、(成功した)組み立てスキャニングアプローチを実装するが、最終的にcluster_registrations_in_a_few_extension_methodsアプローチを発見しました自分自身や他のプログラマーのために読むことがはっきりしています。 登録されたクラスが定義されている場所の近くで登録のクラスタリングを維持すると、登録されたクラス自体に関連するメンテナンスよりもメンテナンスがずっと少なくなります。

+0

私は拡張メソッドを使いました。そして、それは動作します。アセンブリスキャンのアプローチは私には分かりません。 –

関連する問題