1
votes

I recently come across AssemblyNeutral attribute of ASP.net vnext.

If I have to be specific then you will find that attribute usage in Logging respository. https://github.com/aspnet/logging

There are many other repository but this is simple one.

Now as per many blog if we use AssemblyNeutral attribute then that interface or type not tied with assembly so we can defined same interface with AssemblyNeutral attribute in some other framework that want same contract.

So create example I have created my own small logger library in ASP.net vnext class library project but It gives me type cast error.

 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;
        }
    }
}

Now I am trying to use in SampleApp ( Logging Repository SampleApp). You can see that it gives me Cast Error. Why so ?

enter image description here

2

2 Answers

0
votes

The IDE doesn't handle assembly neutral interfaces defined in source properly as yet. That's why you're seeing errors.

0
votes

I am partially agree with Visual Studio 2015 Preview IDE does not support AssemlbyNeutral attribute but Problem is somewhere else.

Actually when we defining Interface or Type again in custom assembly and if we want it support AssemblyNeutral then it must have same namespace as original interface.

In my sample I have done it wrong by putting interface in New Namespace.

I have updated the code and then I build in Visual Studio 2015 Preview It compile and even execute correctly.

So main thing to remember is "Put Assembly Neutral Interface and types in same namespace as it resides for original assembly".

Following is updated code.

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;
        }
    }
}