circular dependencies between dlls with visual studio

前端 未结 9 1122
忘掉有多难
忘掉有多难 2020-12-15 08:00

I have a circular dependency between two functions. I would like each of these functions to reside in its own dll. Is it possible to build this with visual studio?



        
相关标签:
9条回答
  • 2020-12-15 08:34

    How about this:

    Project A

    Public Class A Implements C.IA

    Public Function foo(ByVal value As C.IB) As Integer Implements C.IA.foo
        Return value.bar(Me)
    End Function
    

    End Class

    Project B

    Public Class B Implements C.IB

    Public Function bar(ByVal value As C.IA) As Integer Implements C.IB.bar
        Return value.foo(Me)
    End Function
    

    End Class

    Project C

    Public Interface IA
        Function foo(ByVal value As IB) As Integer
    End Interface
    
    Public Interface IB
        Function bar(ByVal value As IA) As Integer
    End Interface
    

    Project D

    Sub Main()
    
        Dim a As New A.A
        Dim b As New B.B
    
        a.foo(b)
    
    End Sub
    
    0 讨论(0)
  • 2020-12-15 08:36

    You need to decouple the two DLLs, placing the interfaces and implementation in two different DLLs, and then using late binding to instantiate the class.


    // IFoo.cs: (build IFoo.dll)
        interface IFoo {
          void foo(int i);
        }
    
        public class FooFactory {
          public static IFoo CreateInstance()
          {
            return (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();
          }
        }
    

    // IBar.cs: (build IBar.dll)
        interface IBar {
          void bar(int i);
        }
    
        public class BarFactory {
          public static IBar CreateInstance()
          {
            return (IBar)Activator.CreateInstance("Bar", "bar").Unwrap();
          }
        }
    

    // foo.cs: (build Foo.dll, references IFoo.dll and IBar.dll)
        public class Foo : IFoo {
          void foo(int i) {
            IBar objBar = BarFactory.CreateInstance();
            if (i > 0) objBar.bar(i -i);
          }
        }
    

    // bar.cs: (build Bar.dll, references IBar.dll and IFoo.dll)
        public class Bar : IBar {
          void bar(int i) {
            IFoo objFoo = FooFactory.CreateInstance();
            if (i > 0) objFoo.foo(i -i);
          }
        }
    

    The "Factory" classes are technically not necessary, but it's much nicer to say:

    IFoo objFoo = FooFactory.CreateInstance();
    

    in application code than:

    IFoo objFoo = (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();
    

    because of the following reasons:

    1. You can avoid a "cast" in application code, which is a good thing
    2. If the DLL that hosts the class changes, you don't have to change all the clients, just the factory.
    3. Code-completion still wroks.
    4. Depending on your needs, you have to call culture-aware or key-signed DLLs, in which case you can add more parameters to the CreateInstance call in the factory in one place.

    -- Kenneth Kasajian

    0 讨论(0)
  • 2020-12-15 08:39

    This question was first in my search for 'dll cyclic dependency', and even if it is 10 years old, it is a shame that most answers points to 'refactoring' which is a very very very stupid advice for large project and was not a question anyway.

    So I need to point out that cyclic dependency are not so dangerous. They are totally ok in unix/linux. They are mentioned in many msdn articles as possible situations with ways to go arround them. They happens in JAVA (compiler solving it by muilti-pass compiling). Saying that refactoring is the only way is like forbidding 'friends' in classes.

    • this pragraph in some begginers guide to linkers (David Drysdale) explains it well for VS-linkers.

    So the trick is to use two-pass compiling: first one that will create just 'import-libs', and the second one that will generate dll's itself.

    For visual studio and any graphic-ide compiling, it is probably still something strange. But if you make your own Makefiles, and have better controll of linker process and flags, than it is not so hard to do.

    Using OP exampe files and mingw-gcc syntax as a concept to show (because i tested it and know for sure that it works ok on windows), one must: - compile/link a.lib and b.lib without specifing cyclic libraries:

    g++ -shared -Wl,--out-implib=a.lib -o a.dll a.obj //without specifying b.lib  
    g++ -shared -Wl,--out-implib=b.lib -o b.dll b.obj //without specifying a.lib
    

    ... will show 'undefined refernce errors' and fail to provide dll-s, but it will create a.lib and b.lib, which we want foor second-pass linking:

    g++ -shared -Wl,--out-implib=a.lib -o a.dll a.obj b.lib  
    g++ -shared -Wl,--out-implib=b.lib -o b.dll b.obj a.lib
    

    and the result is a.dll and b.dll with pretty clean method. Using Microsoft compilers should be simmilar, with their advice to switch link.exe to lib.exe (did not tested it, seems even cleaner, but probably harder to make something productive from it comparing to mingw + make tools).

    0 讨论(0)
提交回复
热议问题