Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load StackExchange.Exceptional dynamically #152

Open
Duxez opened this issue Nov 26, 2018 · 1 comment
Open

Load StackExchange.Exceptional dynamically #152

Duxez opened this issue Nov 26, 2018 · 1 comment

Comments

@Duxez
Copy link

Duxez commented Nov 26, 2018

For a project at my company I am making a package that has to be installed to a bunch of different websites. We want to get errors from error loggers if they are installed. And are currently willing to support Elmah and Exceptional.

My boss however, also wants to only distribute 1 package for 3 different possibilities, these being:

  1. Website with exception logger installed
  2. Website with StackExchange.Exceptional installed
  3. Website with Elmah installed

To make these possible I'm trying to dynamically load the dll's of these logger packages and invoke methods needed or get the parameter.

This working perfectly fine for Elmah by doing for example the following:

Assembly assembly = Assembly.LoadFile(HostingEnvironment.MapPath("~/bin/Elmah.dll"));

    Type type = assembly.GetType("Elmah.ErrorLog");

    object[] parameters = new object[1];
    parameters[0] = null;

    var customResult = type.InvokeMember("GetDefault", BindingFlags.InvokeMethod, null, type, parameters);

    Type myType = customResult.GetType();
    IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

    string result = "";

    foreach (PropertyInfo prop in props)
    {
        if (prop.Name == "Name")
            result = prop.GetValue(customResult, null).ToString();
    }

Which right now simply gets the name of the default ErrorLog

Then getting to Exceptional and trying a similar approach:

Assembly assembly = Assembly.LoadFile(HostingEnvironment.MapPath("~/bin/StackExchange.Exceptional.dll"));

    Type type = assembly.GetType("StackExchange.Exceptional.ExceptionalModule");

    object objectInstance = Activator.CreateInstance(type);

    PropertyInfo info = type.GetProperty("ErrorStore");
    foreach(PropertyInfo property in type.GetProperties())
    {
        LogHelper.Info<Exceptional>(property.Name + ": " + property.GetValue(objectInstance, null));
    }

This piece of code is to try and get the name of the ErrorStore of the Default ErrorStore used. With some logging for testing and such.

However the moment it has to do anything with the "Default" parameter of the "ErrorStore" class which is supposed to return the default ErrorStore. I always get an exception thrown:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentOutOfRangeException: ErrorStore 'type' must be specified
    Parameternaam: settings
    bij StackExchange.Exceptional.ErrorStore.GetFromSettings(ErrorStoreSettings settings)
    bij StackExchange.Exceptional.ErrorStore.GetErrorStoreFromConfig()
    bij StackExchange.Exceptional.ErrorStore.get_Default()
    bij StackExchange.Exceptional.ExceptionalModule.get_ErrorStore()
    --- Einde van intern uitzonderingsstackpad ---
    bij System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
    bij System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,   Object[] parameters, Object[] arguments)
    bij System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    bij System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
    bij System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
    bij h5ysr_package.Exceptions.Exceptional.ExceptionalErrors()
    bij h5ysr_package.DataCollectorSender.<StartCollection>d__3.MoveNext()

Which brought me to the part of the code that is throwing the error:

if (settings.Type.IsNullOrEmpty())
            throw new ArgumentOutOfRangeException(nameof(settings), "ErrorStore 'type' must be specified");

This being part of the Exceptional package and therefore accessible by me via code.

Is there anyway to make sure type gets specified when loading the StackExchange.Exceptional dll dynamically? Or is just not doable?

@NickCraver
Copy link
Owner

I'll admit this really hadn't occurred to me to even try...have you tried explicitly loading the Postgres DLL ahead of the main library, so the types are available in memory? This is only half the issue...I'm not really sure how the settings behavior is going to play there, but will try to poke over the break here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants