Hello Community,
I’m working on the GH plugin in C# VisualStudio. In my project, I have a class(A) with a bunch of parameters(properties), and in another class(B) I want to access some of the properties from class A. What is the best and most efficient way to do so? Are there any GitHub resources related to this? Thanks.
are you talking about instances of both classes ? or are both classes static ?
An simple example of what you re after ?
By Simple I mean some settings like a shop that sells books and parfumes and allows them to add to a chart
here is the sample console app, that chat gpt create:
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
// Base Product class
public class Product
{
public double Price { get; set; }
public Product(double price)
{
Price = price;
}
public override string ToString()
{
return $"Price: {Price:C}";
}
}
// Book class inheriting Product
public class Book : Product
{
public string Title { get; set; }
public Book(double price, string title) : base(price)
{
Title = title;
}
public override string ToString()
{
return $"Book - Title: {Title}, {base.ToString()}";
}
}
// Parfume class inheriting Product
public class Parfume : Product
{
public double Volume { get; set; }
public Parfume(double price, double volume) : base(price)
{
Volume = volume;
}
public override string ToString()
{
return $"Parfume - Volume: {Volume}ml, {base.ToString()}";
}
}
// Cart class to manage a list of products
public class Cart
{
private List<Product> products = new List<Product>();
// Add a product to the cart
public void AddProduct(Product product)
{
products.Add(product);
Console.WriteLine($"{product.GetType().Name} added to cart.");
}
// Print the bill with all products and total price
public void PrintBill()
{
Console.WriteLine("\n--- Bill ---");
double total = 0;
foreach (var product in products)
{
Console.WriteLine(product);
total += product.Price;
}
Console.WriteLine($"Total: {total:C}");
}
}
class Program
{
static void Main(string[] args)
{
Cart cart = new Cart();
while (true)
{
Console.WriteLine("\nChoose an option:");
Console.WriteLine("1. Add a Book");
Console.WriteLine("2. Add a Parfume");
Console.WriteLine("3. Print Bill");
Console.WriteLine("4. Exit");
string choice = Console.ReadLine();
switch (choice)
{
case "1":
// Add a Book
Console.Write("Enter the price of the book: ");
if (double.TryParse(Console.ReadLine(), out double bookPrice))
{
Console.Write("Enter the title of the book: ");
string title = Console.ReadLine();
Book book = new Book(bookPrice, title);
cart.AddProduct(book);
}
else
{
Console.WriteLine("Invalid price entered.");
}
break;
case "2":
// Add a Parfume
Console.Write("Enter the price of the parfume: ");
if (double.TryParse(Console.ReadLine(), out double parfumePrice))
{
Console.Write("Enter the volume of the parfume (in ml): ");
if (double.TryParse(Console.ReadLine(), out double volume))
{
Parfume parfume = new Parfume(parfumePrice, volume);
cart.AddProduct(parfume);
}
else
{
Console.WriteLine("Invalid volume entered.");
}
}
else
{
Console.WriteLine("Invalid price entered.");
}
break;
case "3":
// Print Bill
cart.PrintBill();
break;
case "4":
// Exit
Console.WriteLine("Thank you for shopping!");
return;
default:
Console.WriteLine("Invalid choice. Please try again.");
break;
}
}
}
}
}
Hello @Tom_P,
I will try to make clear what I’m seeking…
I have a class that constructs the door with many inputs ( length, height, width, panel counts, etc,) based on that class I created a custom component “Door” with one output (Brep).
now I want to create a new component called “DoorFrame” that has one input (Brep), I want to connect the “Door’s” output into “DoorFrame’s” input when I change the “Door’s” parameters (e.h height ) the Frames height must change accordingly.
Ok you want your custom data that can be transmitted / linked between components by wires ?
Check this example in the documentation whether it fit s
Thx @Tom_P for your effort ( I don’t need to transmit or link data between components by wire, I just want to access specific data from one component to another. Sorry I couldn’t express this clearly, my bad.) Anyway, I will check the link you provided.
ok so it is more like a global variable ?
check this:
you might also use a static class or the singleton pattern.
There many ways to achieve this. Either you create a method, like “ChangeHeight”, where you change things in all related properties. Or you override the setter of the property “Height”. This requires that Doors and DoorsFrame know each other (= holding a reference each). If you use events and observe changes inside Doors, you can prevent that Doors knows about DoorsFrame (Observer pattern). Note that this is general programming knowledge, and does not fit well to this forum.
@TomTom, I think this forum is for members to share Rhino and Grasshopper-related problems and solutions, whether from a general programming perspective or a simple Rhino (Grasshopper) component. The problem isn’t how to make Doors and DoorsFrame know each other, the problem I encountered is that when a user drops many( more than one) Doors components on GH canvas the DoorsFame does not know from which Doors’ height data should it accept.
If you knew the solution, you could simply tell or give me a hint, or point me to some resource related to this problem. I think that’s the real purpose of the forums in general.
I do have to admit that I have difficulties to understand your question. But I have the feeling that I‘m talking exactly about your problem, but you might not understand my answer. If you don‘t know how to pass references or information inside an application, then you likely missing fundamental knowledge about object-orientated programming. And chances are much higher to find good answers on stackoverflow and similar programming forums. This is a neutral statement and should not been seen as a request to ask the question somewhere else.
From the point of view from the DoorsFrame - what s the rule / relationship, in natural, human language - to find the correct Door ?
the closest measured by centerpoint ? by some intersections ? by some naming ?
Are you tracking all Door-Component-instances ? if yes, how ?
@TomTom, you judge me despite admitting you didn’t understand my question. It’s interesting how confidently you critique what you don’t fully grasp yourself. I have the feeling that maybe you are a great programmer but a little man as a human. Perhaps I should take your advice and look for clearer answers not elsewhere but here, from a dignified person.
Remember: “The machine does not isolate man from the great problems of nature but plunges him more deeply into them.”- Maybe one day you’ll understand the moral of this.
hello @Tom_P,
I’m already hesitant to ask a question here because of @TomTom’s “wise suggestions”. Anyway, I made a pic, maybe it will make it clearer what I’m trying to achieve.
thx
my guess:
(1) to make it really proper:
you have to implement your own data-class “Door” as I wrote here:
your door data wrapped with an IGH_Goo or GH_Goo
(2) if you want to be lazy:
dont pass the entire “door” parameters, but just pass an “DoorId” with a existing Type.
(int or guid)
now “Frame” will receive the Id, and can get the detailed values form some global data/class / whatever you like.
This (2nd approach) is not completely the idea, because your custom Door data should be able to cast to Brep, Curve, Plane …and other Primitive datatypes (or at least inform, that a cast is not possible…“cast from Door to … failed”) … with int or guid it will cast, but the cast is meaningless.
hope this helps - happy coding.
At which point have I hurt your ego? Okay your thread name and first post sounds like a beginner question. So sorry for thinking that you are one on this matter. But by completely misunderstanding my initial post, I really lost interest to tell you anything constructive.
Looking at your last diagram, could I ask what the reason is that the door and frame components are isolated from each other and that the door component seems to be dictating the frame component?
Just thinking about what a data structure that corresponds to how a door might work might look like, I think it seems more reasonable to think hierarchically as to what kinds of objects are hosting other objects. Like a wall can have an opening, and that opening can have a frame, and that frame can have a door. It’s also reasonable to assume that you won’t really need a door without a frame, so I’d just make one component that makes openings with frames, and have an optional input that will add a door to the frame if one is supplied.
I’m also a little confused about reasoning behind your original the question. Grasshopper is a fundamentally functional programming environment. You can beat it into submission so it works in other ways, but best practice is usually to stick with the path of least resistance. Data in grasshopper are objects that tend to function similarly to structs in other languages. And components are (usually) static functions that transform these groups of data in some definable way. It seems like you’re trying to get these components to talk to each other outside of the data flow that would naturally go between them, and I would suggest that is the wrong tactic.
The door component and the frame component shouldn’t represent actual doors and frames, they are functions that construct data that represents doors and frames. To solve your initial problem within the intended programming paradigm of grasshopper, you need to create a component that creates a door object that contains all the information required for the frame object to generate a frame. That way you can pass in 50 door objects and the frame component will make the required frames for all of them. If you absolutely need to couple the data between the door objects and frame objects, the proper solution is to design them as a single object.
Hello @jsb.walker,
Absolutely. That was the core idea of my initial question: to find out what approach would be better.
Back to your question:
I have many components of Doors, they have different inputs ( number of inputs(parameters) as well as types), and I have many DoorFrames( those are all modular and have many parameters). I’m trying to make things simple for users and not overcomplicated. That was the main reason why I separated them. E.g. when a user wants to use another type of door, she just puts it on canvas and connects it to the DoorFrame component. Hence I consider making them as one Component (combined Door and Frame) as you suggested.
Meanwhile, with @Tom_P’s suggestion and advice, I have already managed to successfully communicate with components as I intended. It gives me the ability to leverage my class to get more accurate results ( I mean the technical side of architectural construction, Wall > Opening >
Frame placement and Door placement etc.)
Thank you for your reply.
Thank you @Tom_P again. Appreciate your work.
so which approach did you use ?
@Tom_P,
I did it according to your first suggestion, using a custom IGH_Goo
wrapper for data sharing.
I always try to avoid using global variables.