Click here to Skip to main content
15,921,793 members
Home / Discussions / C#
   

C#

 
AnswerRe: how to find location of an object Pin
Derek Bartram21-Mar-08 15:47
Derek Bartram21-Mar-08 15:47 
GeneralUpdating db using command builder or manualy Pin
baranils20-Mar-08 10:01
baranils20-Mar-08 10:01 
GeneralC# Object Serialization Problem Pin
Jammer20-Mar-08 10:01
Jammer20-Mar-08 10:01 
GeneralRe: C# Object Serialization Problem Pin
ChrisKo20-Mar-08 11:19
ChrisKo20-Mar-08 11:19 
GeneralRe: C# Object Serialization Problem Pin
Jammer20-Mar-08 12:44
Jammer20-Mar-08 12:44 
QuestionHow to receive messages on the same socket sent from multiple UDP client using different ports? Pin
gix6520-Mar-08 8:43
gix6520-Mar-08 8:43 
GeneralRe: How to receive messages on the same socket sent from multiple UDP client using different ports? Pin
Paul Conrad21-Mar-08 10:04
professionalPaul Conrad21-Mar-08 10:04 
GeneralRecursive Generics for Fluent Interfaces [modified] Pin
TWang20-Mar-08 8:16
TWang20-Mar-08 8:16 
Hi,

I am experimenting a bit with fluent interfaces and decided to try to build a fluent interface to describe a screen layout. I started with an idea of how I wanted the interfaces to work together and mainly focused on intellisense:

<br />
screen.SplitVertical()<br />
   .Left.SplitHorizontal()<br />
      .Top.CreateRegion("region1")<br />
      .Bottom.CreateRegion("region2")<br />
   .Right.CreateRegion("main")<br />
   .Done();<br />


I wanted to be able to split the screen into two areas (Left/Right, or Top/Bottom) and then define a named region for that area. Or, I should be able to indefinitely split and area into sub-areas. Furthermore, I wanted to guarantee that once a screen was split, both areas had to be defined into a region -- and I wanted intellisense to help me out on that.

So, I built a set of interfaces to make this happen (not worrying about implementation yet). As I was doing this, I ran into an issue that goes a bit beyond my understanding of generics.

First, I thought to compose a bunch of interfaces that contained verbs, or actions, that can be performed. Each interface had a generic parameter that determined the return type of the verb:

<br />
public interface ITop<X> { X Top { get; } }<br />
public interface IBottom<X> { X Bottom { get; } }<br />
public interface ILeft<X> { X Left { get; } }<br />
public interface IRight<X> { X Right { get; } }<br />
public interface ICreateRegion<X> { X CreateRegion(); }<br />
public interface ISplitVertical<X> { X SplitVertical(); }<br />
public interface ISplitHorizontal<X> { X SplitHorizontal(); }<br />
public interface IDone { void Done(); }<br />


Then, I defined a interface to join multiple interfaces together at each branch in the fluent interface:

<br />
public interface IBranch1<X> :<br />
    ICreateRegion<X>,<br />
    ISplitHorizontal<IBranch2<X>>,<br />
    ISplitVertical<IBranch3<x>> { }<br />
<br />
public interface IBranch2<X> :<br />
    ITop<IBranch1<IBottom<IBranch1<X>>>>, <br />
    IBottom<IBranch1<ITop<IBranch1<X>>>> { }<br />
<br />
public interface IBranch3<x> :<br />
    ILeft<IBranch1<IRight<IBranch1<X>>>>, <br />
    IRight<IBranch1<ILeft<IBranch1<X>>>> { }<br />
</x>


Knowing that this was really ugly code, I decide to build a quick test:

<br />
public static class Foo<br />
{<br />
    public static T FluentFactory<T><br />
    {<br />
        throw new NotImplementedException("Not yet implemented");<br />
    }<br />
<br />
    public static void Bar()<br />
    {<br />
        IBranch1<IDone> screen = FluentFactory<IBranch1<IDone>>();<br />
        <br />
        screen.Create().Done();<br />
<br />
        screen.SplitHorizontal()<br />
            .Top.Create()<br />
            .Bottom.Create()<br />
            .Done();<br />
<br />
        screen.SplitVertical()<br />
            .Left.Create()<br />
            .Right.Create()<br />
            .Done();<br />
<br />
        screen.SplitVertical()<br />
            .Left.SplitHorizontal()<br />
                .Top.Create()<br />
                .Bottom.Create()<br />
            .Right.Create()<br />
            .Done();<br />
    }<br />
}<br />
<br />
static class Program<br />
{<br />
    public delegate void Func();<br />
<br />
    private static void TryAndCatch(Func x)<br />
    {<br />
        try<br />
        {<br />
            x.Invoke();<br />
        }<br />
        catch (NotImplementedException e)<br />
        {<br />
            MessageBox.Show(e.Message);<br />
        }<br />
        catch (TypeLoadException e)<br />
        {<br />
            MessageBox.Show(e.Message);<br />
        }<br />
    }<br />
<br />
    [STAThread]<br />
    static void Main()<br />
    {<br />
        Application.EnableVisualStyles();<br />
        Application.SetCompatibleTextRenderingDefault(false);<br />
        TryAndCatch(Foo.Bar);<br />
}<br />


And, sure enough, I got a TypeLoadException saying that I was using my generics recursively.

I changed the way the interfaces worked a bit, and arrived at this:

<br />
<br />
// all this is the same as first example<br />
public interface ITop<X> { X Top { get; } }<br />
public interface IBottom<X> { X Bottom { get; } }<br />
public interface ILeft<X> { X Left { get; } }<br />
public interface IRight<X> { X Right { get; } }<br />
public interface ICreateRegion<X> { X CreateRegion(); }<br />
public interface ISplitVertical<X> { X SplitVertical(); }<br />
public interface ISplitHorizontal<X> { X SplitHorizontal(); }<br />
public interface IDone { void Done(); }<br />
<br />
public interface IBranch1<X> :<br />
    ICreateRegion<X>,<br />
    ISplitHorizontal<IBranch2<X>>,<br />
    ISplitVertical<IBranch3<x>> { }<br />
<br />
// this is different<br />
    public interface IBranch2<X><br />
    {<br />
        IBranch1<IBottom<IBranch1<X>>> Top { get; }<br />
        IBranch1<ITop<IBranch1<X>>> Bottom { get; }<br />
    }<br />
<br />
    public interface IBranch3<x><br />
    {<br />
        IBranch1<IRight<IBranch1<X>>> Left { get; }<br />
        IBranch1<ILeft<IBranch1<X>>> Right { get; }<br />
    }<br />
</x>


Now, the TypeLoadException goes away and I simply get my (expected) NotImplemented exception.

My question is -- what is different about the first and second approach?

modified on Thursday, March 20, 2008 2:23 PM

GeneralInstantiating Array of objects. Pin
Ravi Mahavrathayajula20-Mar-08 7:29
Ravi Mahavrathayajula20-Mar-08 7:29 
GeneralRe: Instantiating Array of objects. Pin
Russell Jones20-Mar-08 7:51
Russell Jones20-Mar-08 7:51 
GeneralRe: Instantiating Array of objects. Pin
Ravi Mahavrathayajula20-Mar-08 7:59
Ravi Mahavrathayajula20-Mar-08 7:59 
GeneralC# Used to send E-mail Pin
w20920-Mar-08 6:56
w20920-Mar-08 6:56 
GeneralRe: C# Used to send E-mail Pin
J4amieC20-Mar-08 7:20
J4amieC20-Mar-08 7:20 
GeneralRe: C# Used to send E-mail Pin
led mike20-Mar-08 8:16
led mike20-Mar-08 8:16 
QuestionCrystal reports with dynamic databases? Pin
Tammy Meister20-Mar-08 6:06
Tammy Meister20-Mar-08 6:06 
GeneralRe: Crystal reports with dynamic databases? Pin
Paul Conrad21-Mar-08 10:05
professionalPaul Conrad21-Mar-08 10:05 
Question[Message Deleted] Pin
Ravi Mahavrathayajula20-Mar-08 5:43
Ravi Mahavrathayajula20-Mar-08 5:43 
GeneralRe: Initializing the value of a 1d string to 2d string. Pin
CPallini20-Mar-08 5:49
mveCPallini20-Mar-08 5:49 
General[Message Deleted] Pin
Ravi Mahavrathayajula20-Mar-08 6:12
Ravi Mahavrathayajula20-Mar-08 6:12 
QuestionRe: Initializing the value of a 1d string to 2d string. Pin
CPallini20-Mar-08 6:46
mveCPallini20-Mar-08 6:46 
GeneralRe: Initializing the value of a 1d string to 2d string. Pin
PIEBALDconsult21-Mar-08 5:39
mvePIEBALDconsult21-Mar-08 5:39 
GeneralRe: Initializing the value of a 1d string to 2d string. Pin
CPallini21-Mar-08 7:10
mveCPallini21-Mar-08 7:10 
GeneralRe: [Message Deleted] Pin
Christian Graus20-Mar-08 10:31
protectorChristian Graus20-Mar-08 10:31 
GeneralRe: [Message Deleted] Pin
PIEBALDconsult21-Mar-08 5:38
mvePIEBALDconsult21-Mar-08 5:38 
GeneralRe: [Message Deleted] Pin
Paul Conrad21-Mar-08 9:18
professionalPaul Conrad21-Mar-08 9:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.