[Mono-list] Assembly mutual dependencies or chicken-and-eggproblem

Jonathan Pryor jonpryor@vt.edu
Mon, 12 Jan 2004 22:03:49 -0500


There shouldn't be any problems with your build system and mcs.  If
there is, it's an mcs bug (and please file it :-).

In general, if it works with CSC.EXE, it should work with mcs. 
(Exceptions for language implementation bugs in CSC.EXE, which accepts
some constructs which are not permitted by the ECMA standard.)

 - Jon

On Mon, 2004-01-12 at 08:10, Jaroslaw Kowalski wrote:
> Thanks for your answer.
> 
> Actually I've developed a foolproof version of the build process:
> 
> 1. I have a script that creates a "mini" version of business.dll containing
> nothing but all classes and their constructors. The classes inherit from
> their _Stub counterparts.
> 
> 2. I have another script that creates a "mini" version of "stubs.dll"
> containing nothing but all "*_Stub" classes and their constructors. The
> classes inherit "BaseObject".
> 
> 3. The compilation process is:
> 
> a) compile "mini" stubs.dll (references nothing but base.dll)
> 
> b) compile "mini" business.dll (references "mini" stubs.dll - this must use
> the same version and keyfile, to take care of strong names)
> 
> c) compile full stubs.dll (references "mini" business.dll)
> 
> d) full "business.dll" can be recompiled now against full stubs.dll.
> 
> This may cause warnings (or even errors) with compilers that complain that
> "business.dll" is not found when compiling "business.dll" (in step "d"), but
> can be easily overcome with:
> 
> csc /out:business.dll /r:path_to\stubs.dll /r:\path_to\mini_business.dll
> business*.cs
> 
> Actually csc produces only a warning so I need to reference only
> "stubs.dll".
> 
> DO YOU SEE ANY POTENTIAL PROBLEMS WITH THIS AND MCS?
> 
> Jarek
> ----- Original Message ----- 
> From: "Jonathan Pryor" <jonpryor@vt.edu>
> To: "Jaroslaw Kowalski" <jaak@zd.com.pl>
> Cc: "Mono List" <mono-list@ximian.com>
> Sent: Monday, January 12, 2004 1:52 PM
> Subject: Re: [Mono-list] Assembly mutual dependencies or
> chicken-and-eggproblem
> 
> 
> > You note that System.dll and System.Xml.dll are mutually dependent.
> > They are built, however, by referring to the previous versions of the
> > assemblies.  So System.dll "version" (build?) 101 is built against
> > System.Xml.dll build 100 (previous build), and System.Xml.dll (which is
> > built after System.dll) can depend System.dll build 101 (current).
> >
> > It doesn't look like this will easily work for your scenario.
> >
> > The simple thing to do would likely be to break the dependency, and have
> > the Stub objects just refer to the other Stub objects.  The non-stub
> > objects can then expose new methods/properties, offering the
> > properly-cast stub objects for consumption.
> >
> > Pro: No mutual dependencies between assemblies; if the user stays within
> > the "tablename" classes, they'll never see the Stub classes.
> >
> > Con: Requires that the user-editable classes have boilerplate code (the
> > method/property overrides that expose the correct type).
> >
> > Example:
> >
> > // Assembly: Base.dll
> > class BaseObject {}
> >
> > // Assembly: Stubs.dll
> > class Table1_Stub : BaseObject {
> > public Table2_Stub Table2 { get; set; }
> > // ...
> > }
> >
> > // Assembly: Business.dll
> > class Table1 : Table1_Stub {
> > public new Table2 Table2 {
> > get {return (Table2) base.Table2;}
> > set {base.Table2 = value;}
> > }
> > // ...
> > }
> >
> > If the boilerplate code is an issue (and it could be, with enough table
> > values), introducing a "_Impl" class might work.  It would have to be in
> > the same assembly as the "tablename" classes, but I would think this
> > would work:
> >
> > // Both of these in "Business.dll"
> > // You could probably use CodeDom to generate the _Impl classes,
> > // since it needs to be in the same language as Table1.
> > class Table1_Impl : Table1_Stub {
> > public new Table2 Table2 {
> > // same as Table1, above
> > }
> > }
> >
> > class Table1 : Table1_Impl {}
> >
> > To answer your questions:
> >
> > > Q1: Do you see any problems in the long run? [with original approach]
> >
> > It's a complicated build process, and if the API exposed by the classes
> > ever radically changes (new DB schema, etc.) I think you'd have to start
> > the build "from scratch" (new stub classes, etc.).
> >
> > > Q2: Do you have any better ideas?
> >
> > See above.
> >
> > > Q3: I'd like to be able to use VB.NET or JScript.NET for
> > BUSINESS_OBJECTS.dll while STUBS.dll will remain C#. Do you this this is
> > doable?
> >
> > Yes.  The "barrier" between languages is the .netmodule or the
> > Assembly.  Since each .dll is a different assembly, it should be fairly
> > straightforward to use different languages in this manner.
> >
> > > Q4: I know there can be issues with strong-names, but I believe it
> > should work. Am I right?
> >
> > I would think so, but I'm not the strong-name expert.
> >
> >  - Jon
> >
> > On Fri, 2004-01-09 at 18:38, Jaroslaw Kowalski wrote:
> > > Hi guys!
> > >
> > > I'm implementing a Data Access Layer (with a source code generator) in
> C#
> > > and I'm having a conceptual problem with partitioning my design into
> > > assemblies as it involves mutual dependencies.
> > >
> > > Maybe someone can give me some advice?
> > >
> > > Problem statement (a bit long - sorry)
> > >
> > > 1. The system represents database entities as objects (O/R mapping)
> > >
> > > 2. All entities ultimately derive from some base class that provides
> common
> > > functionality. Let's call it BaseObject.
> > >
> > > 3. On top of that there's a C# code (generated by some stub generation
> > > utility) that creates a class for each database table. Class is named
> > > "tablename_STUB" and derives from "BaseObject".
> > >
> > > 4. I'd like the user to be able to implement additional methods so I
> create
> > > another class for each database table, called "tablename". The idea is
> that
> > > this class will never be re-generated while "tablename_STUB" will be
> > > regenerated whenever the database schema changes.
> > >
> > > So basically I have:
> > >
> > > class BaseObject {}
> > > class SomeTable_Stub : BaseObject { }
> > > class SomeTable : SomeTable_Stub { }
> > >
> > > 5. I want the instance of "SomeTable_Stub" to be able to return
> references
> > > to "SomeTable" objects. This will be used to represent foreign key
> > > relationships and I don't want to clutter SomeTable with any boilerplate
> > > code. So this needs to be done in the Stub class and inherited.
> > >
> > > Now I'd like to partition the system into separate assemblies:
> > >
> > > BASE - which will contain BaseObject and helper stuff
> > > STUBS - which will contain "_Stub" classes (regenerated after the schema
> > > changes)
> > > and
> > > BUSINESS_OBJECTS - which contains classes without "_Stubs".
> > >
> > > My problem is that there's a mutual dependency between STUBS and
> > > BUSINESS_OBJECTS. So I'd need STUBS.dll referencing BUSINESS_OBJECTS.dll
> and
> > > vice versa.
> > >
> > > I don't know how to accomplish it best.
> > >
> > > I've looked at mono makefiles and found that "System.dll" references
> > > "System.Xml.dll" and "System.Xml.dll" references "System.dll". Somehow
> we
> > > have a chicken-and-egg problem because it's not directly buildable.
> > >
> > > I came up with the following idea to build this project:
> > >
> > > 1. Build BASE.dll
> > > 2. Create a small assembly that will have all the classes and methods
> that
> > > STUBS.dll needs from BUSINESS_OBJECTS.dll but they derive from
> BaseObject
> > > and the methods will be stubbed out.
> > > 3. Compile this fake assembly (referencing BASE.dll) and name it:
> > > "BUSINESS_OBJECTS.dll"
> > > 4. Compile "STUBS.dll" passing it a reference to this fake
> > > "BUSINESS_OBJECTS.dll"
> > > 5. Now that we have "STUBS.dll" we can recompile the actual
> > > "BUSINESS_OBJECTS.dll" with it.
> > >
> > > I compiled it and even made it work, but I'm not convinced that this is
> the
> > > best idea.
> > >
> > > Q1: Do you see any problems in the long run?
> > > Q2: Do you have any better ideas?
> > > Q3: I'd like to be able to use VB.NET or JScript.NET for
> > > BUSINESS_OBJECTS.dll while STUBS.dll will remain C#. Do you this this is
> > > doable?
> > > Q4: I know there can be issues with strong-names, but I believe it
> should
> > > work. Am I right?
> > >
> > > Jarek
> > >
> > > P.S. I know I can keep the stubs and business objects in a single
> assembly
> > > (this is actually how I did this before) but want to evaluate the
> > > possibility of separating stubs and keeping them pre-compiled. The
> stubgen
> > > phase takes a considerable amount of time and the stubs are getting
> large
> > > (over 1MB of source code for a large database) so the compilation takes
> > > time.
> > >
> > > P.S.2. I'm planning to release my O/R mapping software as open source
> after
> > > I resolve those basic issues and make it work with mono.
> > >
> > > _______________________________________________
> > > Mono-list maillist  -  Mono-list@lists.ximian.com
> > > http://lists.ximian.com/mailman/listinfo/mono-list
> >
> 
> _______________________________________________
> Mono-list maillist  -  Mono-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-list