|
You have to relate classA and classB in some way - the easiest being inheritance, or implementing the same interface.
Inheritance - Have a common base class for these two classes, say ClassAlpha.
Then it should become
// create new Dictionary
Dictionary<string,ClassAlpha> dictA = new Dictionary<string,ClassAlpha>();
// Fill this one
// ...
// Create a copy
Dictionary<string,ClassAlpha> dictB = new Dictionary<string,ClassAlpha>(dictA);
|
|
|
|
|
vaibhav.jape@gmail.com wrote: dictB = dictA
This don't work. You want to copy all the ClassA objects value to ClassB object and store in dictB , right ?
class ClassA
{
public string str = string.Empty;
public ClassA(string str) {
this.str = str;
}
}
class ClassB
{
public string str = string.Empty;
public ClassB(string str) {
this.str = str;
}
} To copy values, you can use
Dictionary<string, ClassA> dictA = new Dictionary<string, ClassA>();
dictA.Add("X", new ClassA("First"));
dictA.Add("Y", new ClassA("Second"));
dictA.Add("Z", new ClassA("Third"));
Dictionary<string, ClassB> dictB = new Dictionary<string, ClassB>(dictA.Count);
foreach (KeyValuePair<string, ClassA> pair in dictA) {
dictB.Add(pair.Key, new ClassB(pair.Value.str));
}
|
|
|
|
|
Hello folks.
It's been a while since I've managed to paint myself into a corner - but have no fear - I have not lost my talent for getting in over my head!
This time I am working with reflection and trying to access different classes generically . But I have run into a problem trying to get some information out of an object when the object's class isn't known until runtime:
public void GetDataFromStaticClassX(string MethodToCall, object[]MethodParms)
{
private const BindingFlags StaticMethodBindings = BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod;
private const BindingFlags InstancePropertyBindings = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty;
private const BindingFlags InstanceMethodBindings = BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod;
object returnedInfo = typeof(X).InvokeMember(MethodToCall, StaticMethodBindings, null, null, MethodParms);
That works: the proper method is called and the result is put in returnedInfo . However, the result could be any of a number of different classes, depending on the value of MethodToCall . The only thing I now for sure about the contents of returnedInfo is that it will implement IEnumerable .
int returnedInfoCount = (int)returnedInfo.GetType().InvokeMember("Count", InstancePropertyBindings, null, returnedInfo , null);
That works too. I can see the proper value being assigned to returnedInfoCount .
Now comes the kicker: I want to access the first entry in returnedInfo . I tried this
object myData = returnedInfo.GetType().InvokeMember("Item", InstanceMethodBindings, null, returnedInfo, new object[] {0});
No luck. The exception says method Item is not found.
returnedInfo.GetType().InvokeMember("MoveNext", InstanceMethodBindings, null, returnedInfo, null);
object myData = returnedInfo.GetType().InvokeMember("Current", InstanceMethodBindings, null, returnedInfo, null);
Also dies - "MoveNext" is not found.
Does anyone have any ideas of how I can get at the first entry in returnedInfo ?
Many thanks if you are kind enough to look into this.
Even more if you have a suggestion/solution/idea/words of encouragement...
edit: small error in the example code
Clive Pottinger
Victoria, BC
modified on Wednesday, July 23, 2008 6:54 PM
|
|
|
|
|
Not sure I understood you correctly, but if your type implements IEnumerable,
that means exactly one thing: it has a GetEnumerator() method.
So take it from there, get that Enumerator and use it, IMO no further reflection is required.
And a foreach would do that automatically, so why don't you try:
foreach(MyType item in myEnumerableType) {
item.SomeMethod();
}
|
|
|
|
|
Thanks Luc, but it won't work. However, building on your example may make it a little simpler to illustrate my problem:
public void myGetData(string myEnumerableTypeName)
{
object myEnumerableType = (code that returns myEnumerableType as an object)
foreach(MyType item in myEnumerableType)
{
item.SomeMethod();
}
}
Note that I have myEnumerableType, but only as an instance of an object, and objects don't implement IEnumerable.
If I could cast myEnumerableType as an IEnumerable object, then I could write
foreach(MyType item in (IEnumerable)myEnumerableType) But, IEnumerable is an interface, so casting is not allowed.
If I could dynamically implement IEnumerable, perhaps
foreach(MyType item in myEnumerableType:IEnumerable) but the Gods of Syntax threw a bolt of lighting at me for just suggesting it.
I can get the original type of myEnumerableType
Type origType = myEnumberableType.GetType(); Again, if I could dynamically cast then I could do
foreach(MyType item in ((Type)origType)myEnumerableType) but that time the GoS punished me by replacing all my screensavers with jpegs of Ugly Betty.
Clive Pottinger
Victoria, BC
|
|
|
|
|
Hi Clive,
First a few minor corrections to your message:
cpotting wrote: but only as an instance of an object, and objects don't implement IEnumerable.
- objects are instances of classes
- classes can implement an interface
- objects can be cast to an interface, the compiler will accept, the run-time check
may fail; in your case, it cannot prove the object IS an instance of an IEnumerable
class, so it refuses to cast.
Now IMO this is the right plan of attack:
- get your object;
- use reflection to execute its GetEnumerator() method and store the result as a
new object (of type IEnumerator), say myEnumerator.
- on myEnumerator, call methods Reset(), MoveNext() and the property Current
as you see fit; no need for reflection here.
This is code I have running:
public override void Run(int arg) {
MyList list=new MyList();
IEnumerator ienumer= typeof(MyList).InvokeMember("GetEnumerator", InstanceMethodBindings, null, list, null)
as IEnumerator;
log("ienumer="+ienumer);
while (ienumer.MoveNext()) log((string)ienumer.Current);
}
public class MyList : IEnumerable {
private List<string> list=new List<string>();
public MyList() {
list.Add("aaa");
list.Add("bbb");
list.Add("ccc");
}
public IEnumerator GetEnumerator() { return list.GetEnumerator(); }
}
</string></string>
Hope this helps.
modified on Wednesday, July 23, 2008 8:58 PM
|
|
|
|
|
Luc Pattyn wrote: Now IMO this is the right plan of attack:
- get your object;
- use reflection to execute its GetEnumerator() method and store the result as a
new object (of type IEnumerator), say myEnumerator.
- on myEnumerator, call methods Reset(), MoveNext() and the property Current
as you see fit; no need for reflection here.
This is code I have running:
public override void Run(int arg) {
MyList list=new MyList();
IEnumerator ienumer= typeof(MyList).InvokeMember("GetEnumerator", InstanceMethodBindings, null, list, null)
as IEnumerator;
log("ienumer="+ienumer);
while (ienumer.MoveNext()) log((string)ienumer.Current);
}
public class MyList : IEnumerable {
private List list=new List();
public MyList() {
list.Add("aaa");
list.Add("bbb");
list.Add("ccc");
}
public IEnumerator GetEnumerator() { return list.GetEnumerator(); } // LINE WAS MISSING!
}
Thanks again, Luc.
I did not see this and your next post until after I posted my answer. But it is enlightening to see your approach anyway.
There would be two problems with implementing the solution you give above:
1) It requires the me to declare ienumer as type IEnumerable . I do not have this ability (I think it is because we are still using .NET 2.0 here).
2) the line
while (ienumer.MoveNext()) log((string)ienumer.Current); requires that the type returned by ienumer.Current be hardcoded as string . But I cannot hardcode the type, because, in my situation, I may be working on MyList , or MyIntList , or MySomeOtherClassList ...
None the less, your suggestions got me past both issues and my code is working wonderfully. I know I would still be floundering about if it wasn't for guru's like you and the rest of the TheCodeProject folks.
Cheers!
Clive Pottinger
Victoria, BC
|
|
|
|
|
Hi Clive,
You're welcome. Yours was an interesting question, and I happened to have been
investigating IEnumerable and IEnumerator all day. My reflection experience is
limited so I took the opportunity you offered.
cpotting wrote: It requires the me to declare ienumer as type IEnumerable. I do not have this ability (I think it is because we are still using .NET 2.0 here).
I have been running my tests targetting 2.0
But ienumer is an IEnumerator, not an IEnumerable, maybe that got you fooled somehow.
cpotting wrote: requires that the type returned by ienumer.Current be hardcoded as string.
I am not saying you must do it this way, the only thing I meant was once you got
an IEnumerator, it is a real one, you can use it with managed code without reflection,
but yes you have to somehow cast Current to the appropriate type so you can really
use it. But this may well be doable with little or no reflection. Certainly
the MoveNext() does not need reflection at all.
|
|
|
|
|
Hi Clive,
FYI: I just learned that static classes can't implement interfaces, maybe that is
what held you back. My experiments were on instances right away, but I just tried
to simplify to something static and started to get compile errors.
Of course, an explicit call to a GetEnumerator method is always possible, and
a properly implemented Enumerator always returns a new object, with its own
current pointer, so multiple enumerators could be walking the same IEnumerable
at their own pace.
|
|
|
|
|
An even cleaner approach is by replacing the Invoke statement by:
IEnumerator ienumer=(IEnumerator)typeof(IEnumerable).
InvokeMember("GetEnumerator", InstanceMethodBindings, null, list, null);
|
|
|
|
|
I GOT IT ! ! !
Thank you Luc. Your suggestion of using Enumerator helped me find the solution.
public void GetDataFromStaticClassX(string MethodToCall, object[]MethodParms)
{
private const BindingFlags StaticMethodBindings = BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod;
private const BindingFlags InstancePropertyBindings = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty;
private const BindingFlags InstanceMethodBindings = BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod;
object returnedInfo = typeof(X).InvokeMember(MethodToCall, StaticMethodBindings, null, null, MethodParms);
int returnedInfoCount = (int)returnedInfo.GetType().InvokeMember("Count", InstancePropertyBindings, null, returnedInfo , null);
object enumeratorObj = returnedInfo.GetType().InvokeMember("GetEnumerator", InstanceMethodBindings, null, returnedInfo , null);
object moved = enumeratorObj .GetType().InvokeMember("MoveNext", InstanceMethodBindings, null, enumeratorObj, null);
object data = enumeratorObj .GetType().InvokeMember("Current", InstancePropertyBindings, null, enumeratorObj, null);
}
That did it:
enumeratorObj is set to an object that reflects returnedInfo 's enumerator.
moved gets set to true, showing that the call to the enumerator worked.
data gets set to the first entry in returnedInfo - YEAH!!!!
Thanks again.
Clive Pottinger
Victoria, BC
|
|
|
|
|
Hi Clive,
I continued looking for a way without calling GetEnumerator explicitly, and this
now works fine for me:
public override void Run(int arg) {
Type type=Type.GetType("LPExplorer.CPTest_Enumerator+MyList");
log("type="+type);
IEnumerable aList=System.Activator.CreateInstance(type) as IEnumerable;
log("aList="+aList);
if (aList!=null) foreach (string s in aList) log(s);
}
public class MyList : IEnumerable {
private List<string> list=new List<string>();
public MyList() {
list.Add("aaa");
list.Add("bbb");
list.Add("ccc");
}
public IEnumerator GetEnumerator() { return list.GetEnumerator(); }
}
</string></string>
So once the object (aList) exists I don't need reflection to enumerate, provided
I know (or the code somehow finds out) what the type of the items is.
As I mentioned before, aList must be an object, i.e. an instance; it would not work
on static classes.
|
|
|
|
|
i have one dropdownlist suppose: ddl_Technologytype and a textbox: txt_technology.
i have a database name: tech .
and 2 tables in this database : tb_techtype and tb_ tech
ddl_technology have some items , such as ASP,C, VB,JAVA.. and one item as OTHERS .
Now the issue is that when i select the item OTHERS from ddl it shows the textbox ie txt_technology.
and now i have to enter some text to the textbox. So, i will enter the text and then i will click submit button, at this time if the text that is entered in textbox is already present in the ddl then we have to show a message popup "Value is already present in the list" and if text in textbox is not present in ddl then should get added in ddl items when next time i open the page .
and we have to use the database, and would also like to know the process without database .
Please can anyone help me out since i am a beginner , i want solution from both using database and without database.
Thank you.
|
|
|
|
|
listen, if you can´t get an anser shortly i can tell you that later
|
|
|
|
|
please nelson send the reply fast , if posible then by today .
thank you
|
|
|
|
|
listen, what you request it´s not hard, but it takes lots of time to code and debug!!!
So, read the following and if you became stuck ask here in the forum anyone can help you there stay cool.
(i assume you mean that dropdownlist = combobox)
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Visible = false;
comboBox1.Items.Add("ASP"); //0
comboBox1.Items.Add("C#"); //1
comboBox1.Items.Add("VB"); //2
comboBox1.Items.Add("Javascript"); //3
comboBox1.Items.Add("PHP"); //4
comboBox1.Items.Add("Other"); //5
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 5)
{
textBox1.Visible = true;
}
else
{
textBox1.Visible = false;
}
}
private void button1_Click(object sender, EventArgs e)
{
comboBox1.Items.Add(textBox1.Text);
}
Try that easy exemple but that´s not enought! The solution without using a database doesn´t exist!
How and where would you store the data from new values added to the textbox?
And as you can see, each time you load your application your combox will only have the old values not the new added items. You noticed it already, right?
What you have to do instead is this:
create a table (if you don´t have one already) to fill up the combobox, so when you press button new values from the textbox will be added to the table.
1) create table tech with: id int, name varchar(50)
id | name
1 | ASP
2 | c#
3 | VB
4 | HTML
5 | PHP
6 | C++
...etc
2) create a SQL store procedure to fill up/load your combox (trigger it with a load_form event)
SQL:
create procedure tech_all
as
begin
select id, name from dbo.tech
end
go
C#:
this is what i do to connect to database and fill combobox:
string CONNECTION_STRING = "..."; // you know this
SqlConnection con_sql = new SqlConnection(CONNECTION_STRING);
SqlCommand cmd = new SqlCommand();
cmd.Connection = con_sql;
cmd.CommandText = tech_all; // the store procedure above
cmd.CommandType = CommandType.StoredProcedure;
con_sql.Open();
SqlDataAdapter sql_da = new SqlDataAdapter();
sql_da.SelectCommand = cmd;
DataTable dt = new DataTable();
sql_da.Fill(dt);
con_sql.Close();
COMBOBOX1.DataSource = dt;
COMBOBOX1.DisplayMember = "name"; // table tech variable
COMBOBOX1.ValueMember = "id"; // table tech variable
3)create a SQL SP to add values to your combobox (trigger it with button_click event)
SQL:
create procedure tech_add
@name as varchar(50)
as
begin
insert into dbo.tech (name)
values (@name)
end
go
C#:
this is what i do to connect to database and add values to combobox:
(check this part i didn´t have time to test)
string CONNECTION_STRING = "...";
SqlConnection con_sql = new SqlConnection(CONNECTION_STRING);
SqlCommand cmd = new SqlCommand();
cmd.Connection = con_sql;
cmd.CommandText = tech_add; // the store procedure above
cmd.CommandType = CommandType.StoredProcedure;
//
command.Parameters.Add("@name", SqlDbType.VarChar).Value = textbox1.text; // your input textbox!!!
//
con_sql.Open();
SqlDataAdapter sql_da = new SqlDataAdapter();
sql_da.SelectCommand = cmd;
DataTable dt = new DataTable();
sql_da.Fill(dt);
con_sql.Close();
COMBOBOX1.DataSource = dt;
COMBOBOX1.DisplayMember = "name"; // table tech variable
COMBOBOX1.ValueMember = "id"; // table tech variable
Change anything you like to fit what you have in mind!
Good Luck
modified on Thursday, July 24, 2008 7:54 PM
|
|
|
|
|
I'm working on a venue booking system.This system allows a person to make a booking for any period during the year(for a whole month or week).My problem is getting my system to check and display available time slots between a specified range.for example: a person may book from 12 August to 30 August,now how do i get the system to check and display available or unavailable slots.i'm using a grid to display all of this so what i want is my grid to shade with a color the booked time slots on a particular day and allow a person to select the slots they prefer on the grid with a different colour.Any help with this will be appreciated.(code,sql statements)
Thanx
|
|
|
|
|
Hi,
you could loop over the days from date1 to date2, by "incrementing" a DateTime, using
DateTime.AddDays(1); and check that each of these days is still free.
And of course you would use DateTime.Date to get rid of the time component when performing
comparisons.
|
|
|
|
|
I think I'll need to do some wizard controls in the future to accommodate for the short-comings of certain users.
I'd need something that supports some databinding, or at least makes it simple to perform databinding actions myself. I did a quick search on CP and found a good deal of Wizard controls, most of them somewhat dated.
Does anyone have any suggestions for a wizard control that's flexible and easy to implement? Any that are packed with features but a pain to implement?
|
|
|
|
|
Sounds like a candidate for an article. Why not write one of your own, and share it with us, especially as you get to define the features you feel you need? If you have specific problems, or just want advice on features, we'll be glad to help. I look forward to seeing this article.
|
|
|
|
|
Indeed, a great article idea. If people wouldn't mind my writing style (that tends to get off topic and so interjected that it reminds me of a heavily nested, maybe a recursive algorithm) and vocabulary, or lack thereof. And don't get me started on tangents... which reminds me of one of my calculus profs for some reason. He always stopped to talk about his statistician friend who counts insects in the woods and looks like a sasquatch... anyway, that sounds like a great idea.
But I'm not sure if I have time to re-invent the wheel. Which is why I wanted to know what people liked to use.
Now that you got me thinking about it though, I'm getting some design thoughts running through my head. It'd be a fun project to do in my off time after I finish my wife's joint story authoring web-app (she's writing a story in conjunction with her friends and one of them is going crazy with her character so she asked me to make something that forced a kind of co-author approval before it can be appended to the main story). My only problem would be coding for the designer. It's not something I've done before. Fortunately, I've got a lot of sample code to go off of and a great community on CP.
|
|
|
|
|
Sounds good. I'm really looking forward to it now though.
|
|
|
|
|
I'm implementing the XmlSchemaProvider attribute and am having some issues defining my XSD. I've created a XSD file which will be an embedded resource in an assembly. I'm attempting to import the MS WSDL types schema so that I can provide a defintion for char datatype, but every way I try and add the namespace and import the schema I get resolution errors. I'm VERY new to XSDs and have some working knowledge of XML so I'm not 100% positive I can do what I want to here, but this is the basic pattern I have seen in many WSDLs for adding support for char datatypes.
I posted this question in the XML message board as well, but was hoping some C#ers out there have come across this same issue while implementing the XmlSchemaProvider attribute.
Any answers or shoves in the right direction would be appreciated.
Below is a sample format for my XSD:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xs0="http://microsoft.com/wsdl/types/"
>
<xs:import namespace="http://microsoft.com/wsdl/types/"/> <!--cannot resolve "http://microsoft.com/wsdl/types/" error here-->
<xs:complexType name="MyComplexType">
<xs:sequence>
<xs:element name="Value" nillable="true">
<xs:complexType>
<xs:choice>
<xs:element name="boolean" type="xs:boolean" />
<xs:element name="byte" type="xs:byte" />
<xs:element name="unsignedByte" type="xs:unsignedByte" />
<xs:element name="short" type="xs:short" />
<xs:element name="unsignedShort" type="xs:unsignedShort" />
<xs:element name="int" type="xs:int" />
<xs:element name="unsignedInt" type="xs:unsignedInt" />
<xs:element name="long" type="xs:long" />
<xs:element name="unsignedLong" type="xs:unsignedLong" />
<xs:element name="float" type="xs:float" />
<xs:element name="double" type="xs:double" />
<xs:element name="decimal" type="xs:decimal" />
<xs:element name="dateTime" type="xs:dateTime" />
<xs:element name="string" type="xs:string" />
<xs:element name="char" type="xs0:char" /> <!--Type http:=
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
|
|
|
|
|
I write a windows service. This program copy file to another location. Program is properly working in on local disk. If I want to copy file between cliend and server i get error: ERROR 5 (0x00000005) Accessing Source Directory \\server\sharedFolder\ Access is denied.
Same code properly working on windows application, but not work in windows service application. I think this problem related about account permission. Windows application use current user name and password, but maybe windows service application use different account information. What can I do?
|
|
|
|
|
|