DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations

Polymorphism in C# Without Classes

A developer explains how this is possible using his open source project, and gives some example code to help get you started.

Thomas Hansen user avatar by
Thomas Hansen
CORE ·
Jul. 26, 18 · Tutorial
Like (4)
Save
Tweet
Share
9.08K Views

Join the DZone community and get the full member experience.

Join For Free

Imagine all the benefits you'd experience if you could somehow apply polymorphism in C# without classes and methods. First of all, there would be far less dependencies in your code, no abstract base classes or interfaces that could potentially break your code in the future, no method signatures that could potentially break in the future, and no static types that could potentially break in the future. Sounds too good to be true? Read on my friend, and I'll show you the glory.

foo.bar
  arg1:hello
  arg2:world

Believe it or not, but the above is actually a functioning piece of computer code. It is an invocation to an "Active Event" who's name if "foo.bar", and it takes two arguments; arg1 and arg2. Its C# implementation might look like the following.

using p5.core;

namespace foo {

  public static class Bar {

    [ActiveEvent (Name = "foo.bar")]
    public static void foo_bar (ApplicationContext context, ActiveEventArgs e)
    {
      var arg1 = e.Args.GetChildValue ("arg1", context, "");
      var arg2 = e.Args.GetChildValue ("arg2", context, "");
      e.Args.Value = arg1 + " " + arg2;
    }
  }
}

What it returns I assume is obvious. However, after invocation the foo.bar "Node" will have the value "hello world." The first piece of code, that didn't really resemble code at all, is actually a relational file format called "Hyperlambda," which just so happens to create a relational Node tree structure, where a Node can have a name, a value, and a bunch of children nodes. Our root node above is called "foo.bar", and it has two children: arg1 and arg2. The values of our arg1 and arg2 nodes are respectively "hello" and "world." If we run the above Hyperlambda or Node structure through our "eval" Active Event, it will result in dynamically invoking our above "foo_bar" method, assuming we have registered the assembly where we declared our method as an "Active Event sink." If we later, for some reason, want to exchange our above C# implementation, we can easily do that, by, for instance, creating another assembly which implements this specific Active Event, and throw out our old assembly or method. The code will still happily accept our new Active Event, as if nothing had changed. This is true even if we change the "signature" of our method, since there are no signatures, only an expectation to a "bunch of nodes." So every single Active Event is arguably interchangeable, with any other Active Event - at least in theory. And a Node reference, is basically a "piece of execution instructions" which is 100% Turing Complete, allowing you to "eval" a bunch of nodes.

If you want to create yet another layer of abstraction, to inject inbetween your code, and the C# code, to facilitate for dynamic polymorphism, during runtime - you could accomplish that with the following Hyperlambda.

create-event:foo.invoke-bar
  .signal
  add:x:/+
    src:x:/@.signal/--
  foo.bar
  set:x:/+2?value
    src:x:/@foo.bar?value
  add:x:/+
    src:x:/@foo.bar/*
  return

At this point, instead of invoking our "foo.bar" Active Event directly, we can invoke "foo.invoke-bar". The latter event will apply all arguments it is given, and invoke "foo.bar" with these arguments, and return the results to the caller. So, at this point, we have created an "adapter" Active Event, which we invoke instead of invoking our C# event directly, which, of course, is easily exchanged with whatever other C# Active Event you choose to create later down the road. In fact, the above is such a common scenario, we could easily create another Active Event, which simply takes one source Active Event as a string, and another destination Active Event as another string, and automatically create an adapter event like the one above - at which point our code would look like the following:

foo.create-adapter-event
  source:foo.invoke-bar
  destination:foo.bar

If we implemented the above "foo.create-adapter-event" in either C# or Hyperlambda, we could create such "adapter events" with simple three liners every time we needed to create an "interface event," which interfaces with our C# code. And every time we needed to exchange the implementation, we could simply re-invoke our above "foo.create-adapter-event" with another destination event (argument), and we would have dynamically applied polymorphism, in C#, without as much as a single compilation occuring, or even risking having other users simultaneously using our events being in different threads being affected - however, all future invocations to "foo.invoke-bar" for each new ApplicationContext instance, would, instead, point to our new "override."

So, all of a sudden we have a dynamic "scripting language" we can combine with C#, to create a dynamic execution environment, allowing us to create a much richer and more flexible plugin architecture, than any amount of C# could possibly ever give us. With the ability to easily apply polymorphism on functionality, without even having to take down our (web) server, or affecting users already consuming our service. And every single method in your solution has been completely "detangled," and are now loosely coupled pieces of functionality, allowing you to juggle your methods as "independent loosely coupled pieces of encapsulated functionality," and exchange them as you see fit, with any other implementation you happen to have laying around. Basically, you have become a magician in loosely coupling, dynamic invocations, and polymorphism - and you have a dynamically interpreted scripting language for your C# solutions. Not bad for a 5 minute long read.

The above Active Event design pattern is implemented in Phosphorus Five. You can download Phosphorus Five here. Phosphorus Five is open source, but also comes with commercial proprietary offerings if you require additional support, or need to use it in closed source projects. Phosphorus Five is in its entirety created by me (the author of this article).

A 3 minutes long video demonstrating the process.

Download Phosphorus Five and play around with it.

csharp Polymorphism (computer science) Event

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • GitLab vs Jenkins: Which Is the Best CI/CD Tool?
  • How Chat GPT-3 Changed the Life of Young DevOps Engineers
  • Practical Example of Using CSS Layer
  • Fixing Bottlenecks in Your Microservices App Flows

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: