Search code examples
workflow-foundationrule-engine

RuleSetDialog and referenced assemblies


I'm trying to open a RuleSetDialog form on a production site but it crashes with message:

FileNotFoundException: Could not load file or assembly 'IBM.Data.Informix, Version=9.0.0.2, Culture=neutral, PublicKeyToken=7c307b91aa13d208' or one of its dependencies. The system cannot find the file specified.

The thing is, this assembly is being referenced in our project but it doesn't exist on a production site since different database will be used.

This is the stack trace:

at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
at System.Workflow.Activities.Rules.SimpleRunTimeTypeProvider.get_ReferencedAssemblies()
at System.Workflow.Activities.Rules.SimpleRunTimeTypeProvider.GetTypes()
at System.Workflow.Activities.Rules.Parser..ctor(RuleValidation validation)
at System.Workflow.Activities.Rules.Design.RuleSetDialog..ctor(Type activityType, ITypeProvider typeProvider, RuleSet ruleSet)

I'm not sure what to do. Everything worked nicely during development and testing since our machines have all drivers installed but this is not the case with our users who install only the required drivers.


Solution

  • I encountered a similar error this week because our needed dll's are not deployed in the application's main folder, but in a separate subfolder. I did not find any working way to tell the RuleEngine where to search for them. Hacking into the AppDomain did not seem the best solution to me.

    In my case the object I use to run the RuleEngine does not have Extension methods and so does not directly use referenced assemblies for its method definitions. The referenced assemblies are not needed for rule validation.

    So my workaround is to tell the rule-engine that there are no referenced assemblies. This I did by writing my own ITypeProvider and passing that to the constructor of the RuleEngine/RuleSetDialog constructor.

    I took the code from the default SimpleRunTimeTypeProvider from github (https://github.com/rashiph/DecompliedDotNetLibraries/blob/master/System.Workflow.Activities/System/Workflow/Activities/Rules/SimpleRunTimeTypeProvider.cs) and adapted the property ReferencedAssemblies (commented 4 LOC) as follows:

        public ICollection<Assembly> ReferencedAssemblies
        {
            get
            {
                if (this.references == null)
                {
                    List<Assembly> list = new List<Assembly>();
                    // ADAPTATION TO ORIGINAL SOURCE: tell the RuleEngine that there are no referenced assemblies and hence no Extension Methods
                    //foreach (AssemblyName name in this.root.GetReferencedAssemblies())
                    //{
                    //    list.Add(Assembly.Load(name));
                    //}
                    this.references = list;
                }
                return this.references;
            }
        }