Greg Delaney
Greg Delaney

Reputation: 81

Create/Use Codefluent CodeDomSubProducer

I'm attempting to create a CodeFluent SubProducer based on CodeFluent's document at: https://www.softfluent.com/documentation/CustomSubProducer_Topic.html

As the document describes, I've created a Visual Studio (2015) C# class library project named CodeDomSubProducer. Within this project I've added the three references for CodeFluent.Model.dll, CodeFluent.Model.Common.dll and CodeFluent.Producers.CodeDom.dll. I also added an interface, ICodeDomSubProducer, and a class, CodeDomSubProducer, with the code supplied in the document.

After compiling the program, I copied the CodeDomSubProducer.dll to %ProgramFiles(x86)%\SoftFluent\CodeFluent\Modeler.

I've altered my model's CFP file as described in the article.

When I attempt to build the model, the following error is presented: CF6003: Type 'CodeDomSubProducer.CodeDomLightProducer, CodeDomSubProducer' is not a CodeDomSubProducer.

Any suggestions on how I can resolve this error would be greatly appreciated.

Thanks!

  [1]: https://www.softfluent.com/documentation/CustomSubProducer_Topic.html

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using CodeFluent.Producers.CodeDom;
    using System.Collections;
    using System.CodeDom;

    namespace CodeDomSubProducer
    {
        interface ICodeDomSubProducer
        {
            // Methods
            void Initialize(CodeDomBaseProducer baseProducer, SubProducer subProducer, IDictionary context);
            void Produce(IDictionary context, CodeCompileUnit unit);
            void Terminate(IDictionary context);
        }
    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
    using System.Xml;
    using System.CodeDom;
    using CodeFluent.Model;
    using CodeFluent.Producers.CodeDom;
    //using CodeFluent.Runtime.Utilities;

    namespace CodeDomSubProducer
    {
        public class CodeDomLightProducer : ICodeDomSubProducer
        {protected static string namespaceUri = "http://www.softfluent.com/codefluent/producers.lightProducer/2005/1";
            public virtual void Initialize(CodeDomBaseProducer baseProducer, CodeFluent.Producers.CodeDom.SubProducer subProducer, IDictionary context)  
            {baseProducer.CodeDomProduction += new CodeDomProductionEventHandler(OnCodeDomProduction); }
            public virtual void Produce(IDictionary context, CodeCompileUnit unit) {}
            public virtual void Terminate(IDictionary context) {}
            private void OnCodeDomProduction(object sender, CodeDomProductionEventArgs e)
            {if (e.EventType == CodeDomProductionEventType.UnitsProducing)
                {if (e.Argument == null)
                        return;
                    foreach (CodeCompileUnit codeCompileUnit in (CodeCompileUnit[])e.Argument)
                    {foreach (CodeNamespace codeNamespace in codeCompileUnit.Namespaces)
                        {foreach (CodeTypeDeclaration codeTypeDeclaration in codeNamespace.Types)
                            {BaseType baseType = UserData.GetBaseType(codeTypeDeclaration);
                                XmlElement xmlElement = (baseType is Set) ? ((Set)baseType).ItemEntity.Element : baseType.Element;
                                List<string> methodsToHide = new List<string>();
                                foreach (XmlAttribute xmlAttribute in xmlElement.Attributes)
                                {if (xmlAttribute.NamespaceURI == namespaceUri)
                                    {if (xmlAttribute.LocalName == "exclude")
                                        {foreach (string method in xmlAttribute.Value.Split('|'))
                                                methodsToHide.Add(method);
                                        } } }
                                for (int i = 0; i < codeTypeDeclaration.Members.Count; i++)
                                {if (codeTypeDeclaration.Members[i] is CodeMemberMethod)
                                    {CodeMemberMethod method = codeTypeDeclaration.Members[i] as CodeMemberMethod;
                                        if (methodsToHide.Contains(method.Name))
                                        {if (((method.Attributes & MemberAttributes.Public) == 0) &&
                                                ((method.Attributes & MemberAttributes.Static) == 0))
                                            {codeTypeDeclaration.Members.Remove(method);
                                                i--;
        } } } } } } } } } }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


  <cf:project defaultNamespace="TwoCollections" 
              xmlns:cf="http://www.softfluent.com/codefluent/2005/1" 
              xmlns:cfx="http://www.softfluent.com/codefluent/modeler/2008/1" 
              xmlns:cfps="http://www.softfluent.com/codefluent/producers.sqlserver/2005/1" 
              xmlns:cfom="http://www.softfluent.com/codefluent/producers.model/2005/1" 
              xmlns:cflp="http://www.softfluent.com/codefluent/producers.lightProducer/2005/1"
              defaultTargetFramework="4.6.1" 
              defaultConnectionString="Database=TwoCollections;Server=\\.\pipe\MSSQL$SQLEXPRESS\sql\query" 
              createDefaultMethodForms="true" 
              createDefaultApplication="false" 
              createDefaultHints="false">
  <cf:import path="Default.Surface.cfp" />
  <cf:producer name="SQL Server Producer" typeName="CodeFluent.Producers.SqlServer.SqlServerProducer, CodeFluent.Producers.SqlServer">
    <cf:configuration 
        connectionString="Database=TwoCollections;Server=\\.\pipe\MSSQL$SQLEXPRESS\sql\query" 
        produceViews="true" targetVersion="Sql2008" 
        targetDirectory="..\TwoCollectionsC.Persistence" 
        cfx:targetProjectLayout="UpdateItems, DontRemove" 
        cfx:targetProject="..\TwoCollectionsC.Persistence\TwoCollectionsC.Persistence.sqlproj" />
  </cf:producer>


  <cf:producer name="BOM Producer" typeName="CodeFluent.Producers.CodeDom.CodeDomProducer, CodeFluent.Producers.CodeDom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1bb6d7cccf1045ec">
    <cf:configuration 
        compileWithVisualStudio="true" 
        targetDirectory="..\TwoCollections" 
        cfx:targetProject="..\TwoCollections\TwoCollections.csproj" 
        codeDomProviderTypeName="CSharp" 
        cfx:targetProjectLayout="Update" >
    <!-- Custom Sub-Producer  -->
      <subProducer typeName="CodeDomSubProducer.CodeDomLightProducer, CodeDomSubProducer" />
    </cf:configuration>
  </cf:producer>


  <cf:entity name="SpaceX" cflp:exclude="Input|Save|Delete" namespace="TwoCollections" categoryPath="/TwoCollections">
    <cf:property name="GUIDx" key="true" />
    <cf:property name="DataX1" />
    <cf:property name="DataX2" />
    <cf:property name="ParentX" cascadeSave="After" cascadeDelete="Before" typeName="{0}.SpaceYCollection" relationPropertyName="ChildY" />
  </cf:entity>
  <cf:entity name="SpaceY" namespace="TwoCollections" categoryPath="/TwoCollections">
    <cf:property name="GUIDy" key="true" />
    <cf:property name="DataY1" />
    <cf:property name="DataY2" />
    <cf:property name="ChildY" typeName="{0}.SpaceX" relationPropertyName="ParentX" />
  </cf:entity>
</cf:project>

Upvotes: 1

Views: 79

Answers (2)

Greg Delaney
Greg Delaney

Reputation: 81

Great thanks to meziantou, based on his spotting the conditional statement error, and one more tweak, the OnCodeDomProduction function's condition should be <> (!=0) and OrElse (||):

if (((method.Attributes & MemberAttributes.Public) != 0) ||
    ((method.Attributes & MemberAttributes.Static) != 0))

This removes the three methods of insert, save, and delete.

The resulting library, however, only complains about not having a save and a delete method.

Upvotes: 0

meziantou
meziantou

Reputation: 21347

A CodeDomSubProducer must implement the CodeFluent.Producers.CodeDom.ICodeDomSubProducer interface from CodeFluent.Producers.CodeDom.dll. In your code, you redeclare the interface. So, the CodeDomLightProducer doesn't implement the expected interface, but another one that has the same methods and the same name.

To make it work you must remove the following code from your producer assembly:

namespace CodeDomSubProducer
{
    interface ICodeDomSubProducer
    {
        // Methods
        void Initialize(CodeDomBaseProducer baseProducer, SubProducer subProducer, IDictionary context);
        void Produce(IDictionary context, CodeCompileUnit unit);
        void Terminate(IDictionary context);
    }
}

Upvotes: 1

Related Questions