ASp.net vnext 中的 AssemblyNeutral 属性

AssemblyNeutral Attribute in ASp.net vnext

我最近遇到了 ASP.net vnext 的 AssemblyNeutral 属性。

如果我必须具体说明,那么您会在日志存储库中找到该属性的用法。 https://github.com/aspnet/logging

还有很多其他存储库,但这是一个简单的存储库。

现在根据许多博客,如果我们使用 AssemblyNeutral 属性,那么该接口或类型不与程序集绑定,因此我们可以在其他一些需要相同契约的框架中使用 AssemblyNeutral 属性定义相同的接口。

所以创建示例我在 ASP.net vnext class 库项目中创建了我自己的小型记录器库,但它给我类型转换错误。

 namespace MyLogger
{
    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public interface ILogger
    {      
        void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter);
        bool IsEnabled(LogLevel logLevel);
        IDisposable BeginScope(object state);
    }

    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public interface ILoggerFactory
    {       
        ILogger Create(string name);
        void AddProvider(ILoggerProvider provider);
    }
    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public interface ILoggerProvider
    {        
        ILogger Create(string name);
    }

    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public enum LogLevel
    {
        Verbose = 1,
        Information = 2,
        Warning = 3,
        Error = 4,
        Critical = 5,
    }

    public class MyLogger : ILogger
    {
        public IDisposable BeginScope(object state)
        {
            return null;  
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return true;
        }

        public void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
        {
            System.IO.File.AppendAllText("C:\Testlog.txt", "This is test log" + System.Environment.NewLine);
        }
    }

    public class MyLoggerProvider : ILoggerProvider
    {
        private readonly Func<string, LogLevel, bool> _filter;

        public MyLoggerProvider(Func<string, LogLevel, bool> filter)
        {
            _filter = filter;
        }

        public ILogger Create(string name)
        {
            return new MyLogger();
        }       
    }

    public static class MyLoggerExtentions
    {
        public static ILoggerFactory AddMyLogger(this ILoggerFactory factory, Func<string, LogLevel, bool> filter)
        {
            factory.AddProvider(new MyLoggerProvider(filter));
            return factory;
        }
    }
}

现在我正在尝试在 SampleApp 中使用(Logging Repository SampleApp)。你可以看到它给了我 Cast Error。为什么这样 ?

IDE 目前还不能正确处理源代码中定义的程序集中性接口。这就是您看到错误的原因。

我部分同意 Visual Studio 2015 预览版 IDE 不支持 AssemlbyNeutral 属性,但问题出在其他地方。

实际上,当我们在自定义程序集中再次定义接口或类型时,如果我们希望它支持 AssemblyNeutral,那么它必须具有与原始接口相同的命名空间。

在我的示例中,我把接口放在新命名空间中做错了。

我已经更新了代码,然后我在 Visual Studio 2015 Preview 中构建它编译甚至正确执行。

所以要记住的主要事情是 "Put Assembly Neutral Interface and types in same namespace as it resides for original assembly"。

以下是更新后的代码。

namespace Microsoft.Framework.Logging
{
    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public interface ILogger
    {
        void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter);
        bool IsEnabled(LogLevel logLevel);
        IDisposable BeginScope(object state);
    }

    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public interface ILoggerFactory
    {
        ILogger Create(string name);
        void AddProvider(ILoggerProvider provider);
    }

    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public interface ILoggerProvider
    {
        ILogger Create(string name);
    }

    #if ASPNET50 || ASPNETCORE50
    [Microsoft.Framework.Runtime.AssemblyNeutral]
    #endif
    public enum LogLevel
    {
        Verbose = 1,
        Information = 2,
        Warning = 3,
        Error = 4,
        Critical = 5,
    }
}

namespace MyLogger
{


    public class MyLogger : ILogger
    {
        public IDisposable BeginScope(object state)
        {
            return null;
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return true;
        }

        public void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
        {
            System.IO.File.AppendAllText("C:\Testlog.txt", "This is test log" + System.Environment.NewLine);
        }
    }

    public class MyLoggerProvider : ILoggerProvider
    {
        private readonly Func<string, LogLevel, bool> _filter;

        public MyLoggerProvider(Func<string, LogLevel, bool> filter)
        {
            _filter = filter;
        }

        public ILogger Create(string name)
        {
            return new MyLogger();
        }
    }

    public static class MyLoggerExtentions
    {
        public static ILoggerFactory AddMyLogger(this ILoggerFactory factory, Func<string, LogLevel, bool> filter)
        {
            factory.AddProvider(new MyLoggerProvider(filter));
            return factory;
        }
    }
}