WPF多數類概念性註冊加自動掃描

孤沉發表於2024-03-09

在java中springboot的配置應用了自動掃描

@ComponentScan(value = {"com.example", "com.fox"})

而對於Asp.Net Core 可以使用Scrutor

    static void Main(string[] args)
    {
        var collection = new ServiceCollection();
        collection.Scan(action => 
        	action.FromAssemblyOf<IScanAssemblyMarker>()
        	
            .AddClasses(@class => @class.Where(t => t.Name.EndsWith("Service")))
            .UsingRegistrationStrategy(RegistrationStrategy.Throw)
            .AsMatchingInterface()
            .WithScopedLifetime()
            
            .AddClasses(@class => @class.Where(t => t.Name.EndsWith("Repository")))
            .UsingRegistrationStrategy(RegistrationStrategy.Throw)
            .AsMatchingInterface()
            .WithSingletonLifetime());
    
        foreach (var item in collection)
        {
            var log = $"Service: {item.ServiceType.FullName} Lifetime: {item.Lifetime}\nInstance: {item.ImplementationType?.FullName}\n";
            Console.WriteLine(log);
        }
    }

唯獨WPF沒有,悲催,所以他時常是這樣的

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
      containerRegistry.RegisterScoped<IHeaderItemRepository, HeaderItemRepository>();
      containerRegistry.RegisterScoped<IHeaderService, HeaderItemService>();

      containerRegistry.RegisterForNavigation<GeneratorView, GeneratorViewModel>();
}

我這個都算寫的少了,多的可長達20行也是可以的,雖然Prism內建了Module,可以模組化分佈寫
但是我們可以自己實現一個掃描器
只需要用到反射
眾所周知,看程式碼

public static void GetParentInfo()
{
    Type type = typeof(SubClasses);
    Type baseType = type.BaseType;
    Console.WriteLine("父類"+baseType.Name);         //獲取父類

    Type[] interfaces= type.GetInterfaces();
    foreach (Type iface in interfaces) 
    {
        Console.WriteLine("父類介面"+iface.Name);       //獲取所有父類介面
    }
}

public static void GetSubClassesInfo() 
{
    var typesImplementingC = Assembly.GetExecutingAssembly().GetTypes()
    .Where(t => typeof(IParent).IsAssignableFrom(t) && !t.IsInterface);

    foreach (var type in typesImplementingC)
    {
        Console.WriteLine("子類: " + type.Name);
        Console.WriteLine("平類:"+type.BaseType.Name);
    }
}

我這裡提供兩點思路,1、掃描程式集,2、自定義介面去註冊

 public interface IPrismComponent
 {

 }
public void Register()
{
    var assembly = Assembly.GetExecutingAssembly(); // 獲取當前執行的程式集
    var types = assembly.GetTypes()
        .Where(myType => myType.IsClass && !myType.IsAbstract && typeof(IPrismComponent).IsAssignableFrom(myType)); // 找到所有實現了IPrismComponent的非抽象類

    foreach (var type in types)
    {
        containerRegistry.RegisterScoped(typeof(IPrismComponent), type); // 將找到的型別註冊為IPrismComponent的實現
    }
}

唯一有缺陷的地方就是Prism中對於註冊倉儲,註冊服務,註冊導航,用到的方法不一樣,我暫時還沒有想到好的辦法,我有想法,就是觀察這個類是Repository結尾,是Service結尾還是ViewModel結尾,然後給這些類都標註特性

[Register]
public class MainViewModel{}
[Register]
public class MainService{}
[Register]
public class MainRepository{}

接下來我們對不同結尾的類進行分佈處理
使用特性,讓這些類在例項化之前以不同的方式註冊,
不管是單例註冊,瞬時註冊,作用域註冊,UI導航註冊

我們使用AOP去處理,
這樣就不用寫一長串的

 protected override void RegisterTypes(IContainerRegistry containerRegistry)
 {
 
 }

相關文章