7

I have written this code in visual studio 2013 utilizing .net v4.5. The problem I am having is that I am now having to drop down to .net v3.5 and the dynamic keyword is throwing an error as missing an assembly reference. Is there an equivalent type to 'dynamic' in .net v3.5 or a way for me to achieve the same results as below?

I thought I may have found my answer here, but var is throwing errors when I add the .Attributes or .Text property modifications.

private void CreateControl<T>(string objText,
                              Panel pnl,
                              string HTMLTag = "<td>",
                              string applicantID = "",
                              EventHandler hndl = null)
{
    pnl.Controls.Add(new LiteralControl(HTMLTag));
    dynamic obj = Activator.CreateInstance(typeof(T));
    obj.Text = objText;

    if (applicantID != string.Empty)
    {
        obj.Attributes.Add("ApplicantID", applicantID);
    }
    if (hndl != null)
    {
        obj.Click += new EventHandler(hndl);
    }

    pnl.Controls.Add(obj);
    pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
}
Community
  • 1
  • 1
Volearix
  • 1,573
  • 3
  • 23
  • 49
  • 3
    No. in 3.5 there is no `Dynamic` keyword. And you can use `object`. Honestly, unless you use `dynamic` in conjunction with `interop`, something is wrong with your design` – T.S. Feb 17 '14 at 21:32
  • the Object keyword causes the same issues. Tells me there is no definition for 'Attritbutes'|'Text'. Further elaboration might be helpful? – Volearix Feb 17 '14 at 21:34
  • 1
    Is there a reason for the object it instantiates to be dynamic? If you were to apply a type constraint to some `Control` base class/interface, it seems like it should work. – 48klocs Feb 17 '14 at 21:34
  • @48klocs It might be a misuse of the dynamic keyword, but I have no clue which type is coming through the generic class. It could be anything from an asp:textbox to a tinymce:textarea. – Volearix Feb 17 '14 at 21:36
  • What you should of done is derive your controls from same interface and use that instead of `T` – T.S. Feb 17 '14 at 22:02

4 Answers4

5

Instead of trying to hack this together in some bound to fail way and since there isn't a 'dynamic' control in .net v3.5, I have instead decided to just completely forgo this method and wrote some overloads instead. This way seems safer at this point; works the same, just a bit more code...

    #region CreateControl() Overloads
            /// <summary>
            /// Creates a LinkButton control.
            /// </summary>
            /// <param name="objText">.Text property of this LinkButton control.</param>
            /// <param name="pnl">Panel this control will be attached to.</param>
            /// <param name="hndl">Event handler attached to this LinkButton control.</param>
            /// <param name="HTMLTag">Opening tag used to contain this control.</param>
            private void CreateControl(string objText,
                                       Panel pnl,
                                       EventHandler hndl,
                                       string HTMLTag)
            {
                pnl.Controls.Add(new LiteralControl(HTMLTag));
                LinkButton obj = new LinkButton();
                obj.Text = objText;
                obj.Click += new EventHandler(hndl);

                pnl.Controls.Add(obj);
                pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
            }
            /// <summary>
            /// Creates a Label control.
            /// </summary>
            /// <param name="objText">.Text property of this Label control.</param>
            /// <param name="pnl">Panel this control will be attached to.</param>
            /// <param name="HTMLTag">Opening tag used to contain this control.</param>
            private void CreateControl(string objText,
                                       Panel pnl,
                                       string HTMLTag)
            {
                pnl.Controls.Add(new LiteralControl(HTMLTag));
                Label obj = new Label();
                obj.Text = objText;

                pnl.Controls.Add(obj);
                pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
            }
            /// <summary>
            /// Creates the specified literal control.
            /// </summary>
            /// <param name="ControlText">HTML text containing instructions for creating the desired literal control.</param>
            /// <param name="pnl">Panel this literal control will be attached to.</param>
            private void CreateControl(string ControlText, 
                                       Panel pnl)
            {
                pnl.Controls.Add(new LiteralControl(ControlText));
            }
        #endregion
Volearix
  • 1,573
  • 3
  • 23
  • 49
2

Is there an equivalent type to 'dynamic' in .net v3.5

No. dynamic requires .NET 4.0.

or a way for me to achieve the same results as below?

You could use reflection instead of dynamic to create the control and add your event handlers.

However, since this appears to be one of a few custom controls you're creating (given the attributes, etc), you may be able to constrain to an interface or base class, which would allow you to create the items and use those shared properties directly.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Could you point to a reference of the use of reflection to complete this function? I googled it and don't quite follow. – Volearix Feb 17 '14 at 21:38
  • @Volearix You'd have to get the PropertyInfo, and then use SetValue to set the text, etc- see http://msdn.microsoft.com/en-us/library/f7ykdhsy.aspx – Reed Copsey Feb 17 '14 at 21:39
0

Based on your code, it looks like you're writing a generic method to pass in some unknown controls and attach them to a panel.

It also looks like you're dealing with different types of controls; i.e., not all WebControls have Text, and Attributes, AND Click properties;

This is a bit hacky but works in 3.5 - you can just use casting of the various underlying types or interfaces to access the needed properties, something like this:

private void CreateControl<T>(string objText, Panel pnl, string HTMLTag, 
    string applicantID, EventHandler hndl)
        where T : Control, new()
{
    pnl.Controls.Add(new LiteralControl(HTMLTag));
    T obj = new T();

    if (obj is ITextControl) (obj as ITextControl).Text = objText;

    if (applicantID != string.Empty && obj is WebControl)
        (obj as WebControl).Attributes.Add("ApplicantID", applicantID);


    if (obj is IButtonControl)
    {
        (obj as IButtonControl).Text = objText;
        if (hndl != null)
        {
            (obj as IButtonControl).Click += new EventHandler(hndl);
        }
    }

    pnl.Controls.Add(obj as Control);
    pnl.Controls.Add(new LiteralControl(HTMLTag.Insert(1, "/")));
}

Test code:

protected void Page_Load(object sender, EventArgs e)
{
    var panel = new Panel();

    CreateControl<Button>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
    CreateControl<Label>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
    CreateControl<Panel>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
    CreateControl<Literal>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));

    //This won't compile because object doesn't fit <control> constraint
    //CreateControl<object>("test", panel, "<td>", "123", (s, args) => Console.WriteLine("hello!"));
}

To be honest I'm not 100% sure I like this approach. I might use some more specific methods and possibly method overloading to get more specific with different types of control creation, but this may help point you in the right direction.

Note that optional parameters are also not yet "invented" in C# 3.0 which shipped with .net 3.5, so you have to actually pass in all of the values.

Dmitriy Khaykin
  • 5,238
  • 1
  • 20
  • 32
  • No way. Then, why not factory? – T.S. Feb 17 '14 at 22:24
  • @T.S.: Factory is another option sure. I made the disclaimer in the answer that I wouldn't do it this way; however, this code most closely resembles what OP is trying to do and also compiles in .net 3.5. Completely refactoring/rearchitecting OP's code is beyond the scope of SO, is it not? (Though I admit where it's glaringly obvious I will do so when I provide some answers). Here it would be like writing a whole new bunch of code. – Dmitriy Khaykin Feb 17 '14 at 22:26
  • You are double casting all the time, do one as cast and check for null! Just because it fits on a single line, doesn't mean it's faster in any way.. – Trevor Pilley Feb 17 '14 at 22:28
  • The way to do this is to wrap all controls to a common interface and instead of `CreateControl (...)` have `CreateControl (IMySystemControl c, ...)` . I am telling you, people get the keywords and do whatever they like with it :o) – T.S. Feb 17 '14 at 22:30
  • @T:S.: Then he has to subclass all of the controls - these are native asp.net controls he's working with. Then, the subclasses would implement a common interface that contains properties not all of the subclasses ever use, such as for example a Click event on a Literal control. I am not a fan of that idea, personally, either. – Dmitriy Khaykin Feb 17 '14 at 22:32
  • @TrevorPilley: The only double cast is for IButtonControl, and if I were to combine the .Text and .Click parts I'd need to add more logic to create a variable cast as IButtonControl, then set it back to obj. Also casting to an interface isn't expensive from what I understand. – Dmitriy Khaykin Feb 17 '14 at 22:34
  • @DavidKhaykin It is not different than passing Literal control to `CreateControl` and have no click. The problem here is that someone wanted (and achieved) to initialize group of controls in a unified way. But the gains are minimal. What if some controls don't have literal and panel? If I build a robust and scalable system, I unify all controls, including 3rd party and check them to be `IClickable`, `ISelectable` and so on. Here we dealing with case in which someone decided to do it in cool way, leaving of trace of questionable decisions. – T.S. Feb 17 '14 at 22:59
  • @T.S. I disagree that it is no different, particularly with one common interface. That means all subclasses must implement some methods and/or properties that are unused. Sure, you can just make those methods throw a NotImplementedException or the like but it can still be confusing to other developers working with that library. In the second case where you mention multiple interfaces, to make a common method that can handle all cases, you'd end up with similar code as in my answer, unless you go the reflection route, which also has it's downsides and overhead, and still ends up with ugly code. – Dmitriy Khaykin Feb 17 '14 at 23:06
  • Also I'm not sure what you mean, "what if some controls don't have literal or panel" - in this case, the method is specifically adding items to a Panel's ControlCollection. Any object derived from Control can be added. – Dmitriy Khaykin Feb 17 '14 at 23:09
-3

dynamic keyword is available on .net 4.x and is a simple way to store any kind of value, it just resolve his type in runtime. It has been useful to me working with JSON strings.

string jsonValue = "{name:'Pedro',lastName:'Mora'}";
dynamic Variable = new JavascriptSerializer().Deserialize<dynamic>(jsonValue);
return Variable.name;
//It will return "Pedro"

Thing is that you have to be sure that the value won't be null and the properties or attributes or methods or something refered to the object exists and it takes it's values on runtime.

pedritin
  • 47
  • 2
  • 10
  • This in no way answers the question of how to replicate this behavior pre .NET 4.0, which is what the question is asking. – Servy Feb 17 '14 at 21:45
  • @pedritin This isn't my question, please re-read. I'm needing an alternative to dynamic, not how it works. – Volearix Feb 17 '14 at 21:46
  • I'm sorry. I just said what I use it and explain tha it take his type in runtime. I think you should convert it to object, evaluate if is not null and then get its base type. the load the assembly of the type, of something like that. – pedritin Feb 17 '14 at 21:58