0

I have MySolution.MyLibrary class library which I register in MySolution.MyService WCF service using SimpleInjector:

container.Register<IMyLibrary, MyLibrary>(LifeStyle.Singleton);

I need to get the name of the main assembly, MySolution.MyService, in the constructor of MySolution.MyLibrary. I've tried Assembly.* methods but I couldn't manage to do it. Any ideas how I can get the name?

These are what I've tried:

Assembly.GetExecutingAssembly().GetName().FullName
"MySolution.MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

Assembly.GetCallingAssembly().GetName().FullName
"Anonymously Hosted DynamicMethods Assembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"

Assembly.GetEntryAssembly()
null 
dstr
  • 8,362
  • 12
  • 66
  • 106

3 Answers3

1
using System.Diagnostics;
using System.Linq;

...

StackFrame[] frames = new StackTrace().GetFrames();
string initialAssembly = (from f in frames 
                          select f.GetMethod().ReflectedType.AssemblyQualifiedName
                         ).Distinct().Last();

Check this question

Update :

Use below Code for WCF:

var currentAssembly = Assembly.GetExecutingAssembly();
        var callerAssemblies = new StackTrace().GetFrames()
            .Where(x => x.GetMethod() != null && x.GetMethod().ReflectedType != null )
                    .Select(x => x.GetMethod().ReflectedType.Assembly).Distinct()
                    .Where(x => x.GetReferencedAssemblies().Any(y => y.FullName == currentAssembly.FullName));
        var initialAssembly1 = callerAssemblies.Last();

enter image description here

Jophy job
  • 1,924
  • 2
  • 20
  • 38
  • Last() gives me System.Web.Hosting.PipelineRuntime, probably because it's hosted with IISExpress. MySolution.MyService is like 7th in the list. – dstr Jan 17 '18 at 11:40
1

You can simply inject this information:

public class MyLibrary : IMyLibrary
{
    public MyLibrary(string assemblyName) { ... }
}

By registering it as follows:

container.RegisterSingleton<IMyLibrary>(new MyLibrary(
    Assembly.GetExecutingAssembly().GetName().FullName));

Or in case you need to use Auto-Wiring (because MyLibrary contains other dependencies, extract the configuration value into a configuration object:

public class MyLibraryConfig
{
    public readonly string AssemblyName;

    public MyLibraryConfig(string assemblyName) { 
        this.AssemblyName = assemblyName;
    }
}

public class MyLibrary : IMyLibrary
{
    public MyLibrary(MyLibraryConfig config, IOtherDependency dep) { ... }
}

With the following configuration:

container.RegisterSingleton(new MyLibraryConfig(
    Assembly.GetExecutingAssembly().GetName().FullName));

container.Register<IMyLibrary, MyLibrary>(Lifestyle.Singleton)
Steven
  • 166,672
  • 24
  • 332
  • 435
  • I thought you were against passing runtime parameters to injected object constructor :) https://github.com/simpleinjector/SimpleInjector/issues/58#issuecomment-111715956 . I'm looking for a more "automatic" solution, e.g I rather not bother referer with obligatory parameters but I'll change to this if I can't find a way to do it. Thanks. – dstr Jan 17 '18 at 14:54
  • 1
    A runtime parameter is a value that will change throughout the lifetime of the application. In this case the value is fixed and known after startup. That makes it rather a 'configuration' value, not a runtime value. – Steven Jan 17 '18 at 14:57
0

Try something like:

MethodBase entryMethod = null;
var methodFrames = new StackTrace().GetFrames().Select(t => t.GetMethod()).ToList();
foreach (var method in methodFrames)
{
    if (method.Name == "Main" && method.ReturnType == typeof(void)){
        entryMethod = method;
    }
}
Assembly entryAssembly = entryMethod.Module.Assembly;

Haven't tested it though, the idea is to walk the methods until you find a known method from the library like the example looks for a Main method from a console app.

MarkovskI
  • 1,489
  • 2
  • 21
  • 25