C# Accessing a class from a "parent project" in a "child project"?
Asked Answered
V

6

5

Let's say I have multiple projects within a solution. I have the main project parent_project and another project child_project.

How can I access classes / namespaces residing in parent_project from child_project ?

I have already added a Reference to child_project in parent_project so I can't add a Reference to parent_parent in child_project as it would create a circular dependency.

Is this possible?

Vergievergil answered 10/2, 2015 at 9:5 Comment(8)
inherit child_project from parent_project class. if not show me your classesUraemia
That's not exact answer so I'll add it as a comment - you will not be able to add a dual reference, I'd suggest to move common things used in both child and parent into a separate 'common' project and then reference to it from both child and parentLyse
had a same situation. As you said a circular reference is due to dependency of child class's functionality from parent class. If you want to have some common functionality for both and to use it without any hassle , best thing is to move that to a common place for both .Carpospore
This sounds like an XY problem... would you not be better off just making the method in the parent project in the first place?Titograd
Just another interesting thing - in .net 2 MS made such a trick - System.Xml has reference to System and vice versa, but they not allow to do this to anyone else!Lyse
@Lyse That's interesting. Any idea why this was done?Virtuous
@Virtuous no I didn''t dig into it, just heard about it once and verified that it is trueLyse
Are you trying to use the TYPE or an instance of the type? If you want an instance of the type than pass the instance from parent to child.Merrymerryandrew
T
10

If you're sharing logic between projects, you need to isolate that dependency and move it to a shared location (new project for example), restructure your dependencies so that your core logic lives in a core domain-like project or mash your projects together.

The latter is not really the cleanest of solutions. I would recommend thinking about your own question and really try to answer "Why do I NEED a circular reference? How can I restructure so that my dependencies make sense?".

Thomasinethomason answered 10/2, 2015 at 9:13 Comment(3)
Seems to be the general advice, unfortunately the piece of code I'm trying to use is used prolifically throughout the main project and is needed in just a single place in the child project, and the functionality it provides to the child project is relatively minor... It would be a huge amount of work to restructure... was hoping there'd be a quick fix...Vergievergil
No quick fixes, I'm afraid. There is another option but it's a god awful one to be fair and that's to host your parent assembly on a local nuget repo and pull that down into your child project. It's a very, very messy way of achieving, what is in essence, an xcopy of your assembly into the bin folder so I really wouldn't recommend it but it's on the table (honestly, I haven't tried that myself so I can't vouch for it working but in theory it could work.)Thomasinethomason
That way sounds almost as messy as using reflections would be (where you would have to have the dll of your mainproject in referenced :/ )Anglocatholic
L
2

You can inject your dependency using an interface defined in the child project (this can be useful where major refactoring is not possible/too expensive).

e.g. In the child project:

interface IA {
   DoLogicInB();
}

In the parent project:

class ConcreteA : ChildProject.IA
{
    DoLogicInB() { ... }
}

In the child project, where you need the logic:

class ChildB {
   void DoSomethingWithParent(IA logicEngine) {
       logicEngine.DoLogicInB();
   }
}

You need to then be able to inject a concrete implementation of the parent object from outside the child project.

Lyris answered 10/2, 2015 at 9:30 Comment(0)
V
1

FYI

I ended up just copying the logic to a shared location, and "child" projects can access this version. I know from a maintainability point of view this isn't the best solution but it seemed like the best compromise..

Vergievergil answered 10/2, 2015 at 10:17 Comment(3)
Which sounds like Yannicks proposal thereAnglocatholic
Pretty much the same except I copied rather than moving so the main project still accesses its own version.Vergievergil
only problem with that version is though that you need to be careful if anything changes in that code that you do the changes in both code part.Anglocatholic
T
1

I didn't require entire namespace, but just reading some data dictionary or calling one particular method from parent project class. Here is how we got it working.

using System;
using NUnit.Framework;
using System.Collections.Concurrent;

namespace MyProject.tests
{
    public class ParentChildTest
    {
        [Test]
        public void dataAndMethodTest()
        {
            // add the data in parent project
            Parent.propertyCache["a"] = "b";

            // read the data in child project
            Console.WriteLine("Read from child: " + Child.getProperty("a"));

            // use Child project to call method of parent project
            Console.WriteLine("Call from child: Populate method in parent: " + Child.populate("c"));
        }
    }

    class Parent
    {
        // data is in Child project. Parent project just has the reference.
        public static ConcurrentDictionary<string, string> propertyCache = Child.getPropertyCache();

        public static string populate(string key)
        {
            //calculation
            string value = key + key;
            propertyCache[key] = value;
            return value;
        }

        // Pass the parent project method reference to child project
        public static int dummy = Child.setPopulateMethod(populate);
    }

    class Child
    {
        // data store
        static ConcurrentDictionary<string, string> propertyCache = new ConcurrentDictionary<string, string>();

        public static ConcurrentDictionary<string, string> getPropertyCache()
        {
            return propertyCache;
        }

        public static string getProperty(string key)
        {
            if (propertyCache.ContainsKey(key))
            {
                return propertyCache[key];
            }
            return null;
        }

        // reference to parent project method
        static Func<string, string> populateMethodReference = null;

        public static int setPopulateMethod(Func<string, string> methodReference)
        {
            populateMethodReference = methodReference;
            return 0;
        }

        public static string populate(string key)
        {
            return populateMethodReference(key);
        }
    }
}

Using parent project class data in child

  1. Earlier the propertyCache was in parent class. Child needed to access it.
  2. So, the propertyCache has been moved to Child. Parent also reads and populates the same.

Using parent project class method in child

  1. Pass the method reference to the child somehow (by some static method).
  2. use the reference to invoke that parent method.

Output of the program

Read from child: b
Call from child: Populate method in parent: cc
Tapley answered 14/12, 2019 at 9:57 Comment(0)
A
0

I have to say that Yannicks answer is the way to go there normally. In your special situation (as outlined in your comment to his answer) it sounds like that would be problematic. A different way would be (only possible if the mainclass compiles into a dll):

  • Include the compiled dll of the mainproject in the child project
  • Use the methods you need via reflection

This is one possible other route BUT has quite a few pitfalls as reflection has troubles of its own.

Anglocatholic answered 10/2, 2015 at 9:26 Comment(0)
A
-1

Ok so let's say you have a Project with 2 solution in it S1 and S2 and you have reference S1 in S2, inside S1 it you have a class P and in S2 you have three Class defined by user A B an C. now make A inherit P so when you invoke constructor of A it will invoke constructor of P (that's in In S1) noe inside P's Constructor if you want the list of all the class declared in S2 use this code.

    Assembly assembly = this.GetType().Assembly;

    // DefinedTypes will list all Userdefined class
    foreach (var typeInfo 
 inassembly.DefinedTypes ) 
    {
      // typeInfo.FullName //you will have  A B and C
    }
Abulia answered 3/12, 2022 at 20:19 Comment(1)
Please don't post only code as an answer, but also provide an explanation of what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotesWorldshaking

© 2022 - 2024 — McMap. All rights reserved.