question

HiteshMaheshwari-3175 avatar image
0 Votes"
HiteshMaheshwari-3175 asked TimonYang-MSFT commented

Code to check the circular dependency between classes

**Circular dependency between classes


I've tried something this works well, it needs to be checked whether it's correct or if anyone can help me with it.**


 public static class EntitySerializerHelper
     {
         private const byte MaxNumberStackTraceFrameCount = 100;
         public static void HasCircularDependency(this Type entityObjectType)
         {
             CheckStackDepth();
    
             var publicProperties = entityObjectType.GetProperties()
                 .Where(o => o.PropertyType.IsPublic && !o.PropertyType.IsValueType && o.PropertyType != typeof(string)).ToArray();
    
             foreach (var propertyInfo in publicProperties)
             {
                 var typeOfObject = propertyInfo.PropertyType;
    
                 if (typeOfObject.IsGenericType)
                 {
                     if (HasTypeDictionary(typeOfObject))
                     {
                         var keyType = typeOfObject.GetGenericArguments()[0];
                         var valueType = typeOfObject.GetGenericArguments()[1];
    
                         HasCircularDependency(keyType);
                         HasCircularDependency(valueType);
                     }
                     else if (HasEnumerableType(typeOfObject))
                     {
                         var itemType = typeOfObject.GetGenericArguments().Single();
                         HasCircularDependency(itemType);
                     }
                 }
                 else if (typeOfObject.IsClass)
                 {
                     HasCircularDependency(typeOfObject);
                 }
             }
         }
    
         static void CheckStackDepth()
         {
             if (new StackTrace().FrameCount > MaxNumberStackTraceFrameCount)
             {
                 throw new StackOverflowException("StackOverflow");
             }
         }
    
         static bool HasEnumerableType(Type type)
         {
             if (type.IsInterface && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
             {
                 return true;
             }
    
             foreach (var intType in type.GetInterfaces())
             {
                 if (intType.IsGenericType && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                 {
                     return true;
                 }
             }
    
             return false;
         }
    
         static bool HasTypeDictionary(Type typeOfObject)
         {
             return typeOfObject.GetGenericTypeDefinition() == typeof(Dictionary<,>);
         }
     }


dotnet-csharp
· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

What is the usage of this code for? Under what circumstance is the code to be used?

0 Votes 0 ·

It will be used if the parent type has the same type as the child type and child type has the same type as parent type in short circular dependency
EX : A->B and B->A

Calling - Assert.DoesNotThrow(() => typeof(A).HasCircularDependency());

0 Votes 0 ·
 public class A
     {
         public B TypeB { get; set; }
     }
    
     public class B
     {
         public A TypeA { get; set; }
     }
0 Votes 0 ·
Viorel-1 avatar image Viorel-1 HiteshMaheshwari-3175 ·

Probably a simpler case:

 public class Node
 {
    public Node Parent { get; set; }
 }
1 Vote 1 ·

Is 'var publicProperties' the public properties of the type or the properties whose types are public and non-nested?

0 Votes 0 ·

The properties whose types are public and non-nested

0 Votes 0 ·

1 Answer

TimonYang-MSFT avatar image
0 Votes"
TimonYang-MSFT answered TimonYang-MSFT commented

Try the following code:

 class Program
     {
         static void Main(string[] args)
         {
             Type type = typeof(A);
             Type type2 = typeof(B);
             var c1 = type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(t=>t.PropertyType == type2);
             var c2 = type2.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(t=>t.PropertyType == type);
    
             if (c1.Count()!=0 && c2.Count()!=0)
             {
                 Console.WriteLine("They are circularly dependent");
             }
         }
     }
     public class A
     {
         public B TypeB { get; set; }
     }
    
     public class B
     {
         public A TypeA { get; set; }
     }

Did I understand what you mean correctly?

Update:

You said that they are the relationship between the parent type and the child type, but the above example does not seem to reflect this relationship.

If they have an inheritance relationship, then even if we don't know the exact type of the subclass, we should be able to put it in the collection of the parent class, and then use reflection to get the exact type and get all the properties.

     class Program
     {
    
         static void Main() 
         {
             List<A> classes = GetA();
             foreach (var item in classes)
             {
                 Console.WriteLine(item.GetType());
             }
             Console.WriteLine("Press any key to continue...");
             Console.ReadLine();
         }
         public static List<A> GetA() 
         {
             List<A> classes = new List<A>();
             classes.Add(new A());
             classes.Add(new B());
             classes.Add(new C());
             return classes;
         }
     }
    
     class A
     {
         public B TypeB { get; set; }
     }
     class B:A
     {
         public C TypeC { get; set; }
     }
     class C:B
     {
         public A TypeA { get; set; }
     }

If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

This is when we already know about the child class but if we don't know about the child class or the child class can be with multiple values also (ex: Enumerable<B>) then this will not work.

I need to check only with parent type not with the child type.

0 Votes 0 ·

One more thing here is only considered the custom class for circular dependency, not the value type or the string type.

0 Votes 0 ·

If usecase is A->B and B->C and C->A then also it should work

0 Votes 0 ·

I updated the answer, please check.

0 Votes 0 ·