[Mono-list] Assembly mutual dependencies or chicken-and-egg problem

Jonathan Pryor jonpryor@vt.edu
Mon, 12 Jan 2004 07:52:24 -0500


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