|
I have a mini macro language for my application. Something along the lines of:
"Blah -- [SomeTag:SomeParam=SomeValue] -- Blah. Blah, Blah : [SomeTag2:SomeParam2=SomeValue2]"
So, my current implementation parses the string every time my method gets called, does error checking every time, etc. I parse the string with Regex group matching and then do a String.Replace() on the string to replace the macros with the resolved macro strings.
I get called many times with the same format string, but different parameters.
It doesn't really make sense to parse and error check, etc. every time. That'll be a performance hit. Especially with Regex.
How do people typically "compile" the string for tasks like this?
My first idea was to parse and error check the string the first time and replace the macros with a compact fixed string. For example, in the case above, the first time I would compile to:
"Blah -- $A1 -- Blah. Blah, Blah : $B1"
Then I would know that command $A1 means do SomeTag in SomeParam=SomeValue mode. $A2 would mean do SomeTag in SomeParam=SomeValue2 mode. SomeTag2 would be $B1, etc.
This would save me the regex and error checking every time. I would still have to do String.Replace() of course...
The tag operations are not static constants BTW, they come from various places.
Any other ideas?
|
|
|
|
|
SledgeHammer01 wrote: Any other ideas?
My first thought was to try holding onto the Regex rather than throwing it out -- saving time by using more space -- but I tried a couple of small experiments and I didn't see how it would help.
What is "Blah"? If it is a command, with only limited domain, then you could at least make an enumeration and only parse it once, sort of what I did for my CommScript[^] .
|
|
|
|
|
In it's simplest form of explanation, I'm just trying to expand "complex" macros in a string.
For example, say the caller calls me with "My dogs' name is $[User:Dog]". I need to return "My dogs' name is Spot".
I can have simple macros like $[DateTime] or more "complex" macros like $[User:Fullname=true].
I'm already caching the Regex object to save on the Regex engine having to parse the expression every time.
My other idea besides the $A1 / $B2 thing was to maybe on the first parse to build a string for a C# method like:
static void DummyFunc(User user)
{
return String.Format("My dogs' name is {0} and today is {1}.", user.DogName, DateTime.Now);
}
and compile it into a temp assembly. Or to do something similar using expression trees. My first thought went to the generating C# code at runtime and compiling it because doing something like this with expression trees is a big ol' PITA since I would need to call a bunch of functions to expand all the macros available.
|
|
|
|
|
Got bored waiting for your reply to my reply lol, so I tried my generating C# code at runtime and compiling into a temp in-memory assembly and creating a cached delegate to the compiled method. Works like a charm. The code is pretty gangster too ! This is what the XML serializer does I believe.
|
|
|
|
|
It sounds almost like you want to write your own DSL for this. Our very own Sacha Barber wrote a very interesting article about this[^] very topic.
|
|
|
|
|
SledgeHammer01 wrote: I get called many times with the same format string, but different parameters.
10? 1 million? 1 billion?
SledgeHammer01 wrote: That'll be a performance hit. Especially with Regex
Profile the application rather than guessing.
SledgeHammer01 wrote: How do people typically "compile" the string for tasks like this?
I don't because it typically doesn't get called enough. And when it gets called more than a couple of times it is often within something else and the 'rest' of the block has more impact.
If I needed to and given that your expressions look complicated I would probably first start by building a tree of computed expressions as a hashes and use the entire expression as a key (rather than attempting to replace each) and the value is the computed expression.
|
|
|
|
|
Hello developers..sorry for the subject i dont know how to explain my problem i am new in c# and i am working on datagridview combobox cell my problem is
i have to 2 datacomboboxcell in datagridview and i sucessfully bind 1 to another like this
one combocell i select HP then on another combocell it will show hp products but when i go to next row and then select other product like lenovo hp etc so its clear the 1st row combocell where i selected the hp products on it
please help me whats the solution
|
|
|
|
|
It sounds as though there is a problem with your binding, but impossible to guess without seeing your code. Please edit your question and add the required detail.
|
|
|
|
|
if (dgDetail.CurrentRow.Cells["Product"].Value != null)
{
dt = db.select("select PC.id,PC.ProductCode,(Ph.Header + '-'+ PS.SubProduct) Product from tblProductCodes PC INNER JOIN tblProductSub PS on PS.id=PC.SubProductID INNER JOIN tblProductHeader PH on PH.id=PS.Header where PS.id='" + dgDetail.CurrentRow.Cells["Product"].Value.ToString() + "'and PC.id not in (select ProductCode from tblInvoiceDetail)");
ProductCode.DataSource = dt;
ProductCode.ValueMember = "ID";
ProductCode.DisplayMember = "ProductCode";
if (dgDetail.CurrentRow.Cells["ProductCode"].Value != null)
{
dgDetail.CurrentRow.Cells["CostPrice"].Value = objDB.GetDataField("select CostPrice from tblProductCodes where subProductID='" + dgDetail.CurrentRow.Cells["Product"].Value.ToString() + "' and id='" + dgDetail.CurrentRow.Cells["ProductCode"].Value.ToString() + "'", "CostPrice");
}
}
This is my code the product column is for select products and productcode column is for select product's type related to products
|
|
|
|
|
I have a PropertyGrid in an application. I have a problem with a functionallity reverting to a old value if I detect the new value as invalid.
Here is some short information abut the PropertyGrid:
* There are properties which are strings.
* I cannot allow an empty string for any properties.
* I want a revert functionallity to revert to the old value.
* The PropertyGrid is localized so the DisplayName of each property is NOT the same as the name of the property.
With the event
PropertyGrid.PropertyValuechanged I can get what property was changed.
The event's callback pass a
PropertyCalueChangedEventArgs object which I use revert with these properties:
PropertyValueChangedEventArgs.OldValue
PropertyValueChangedEventArgs.ChangedItem.Label
This gets the old value and the DisplayName of the property which was changed.
Here is the class I display in the PropertyGrid:
public class Person
{
public Person()
{
}
public string FirtName
{
get;
set;
}
public string LastName
{
get;
set;
}
public int Age
{
get;
set;
}
}
I use this code to revert back to the old value:
private void Revert(object obj, string name, string oldValue)
{
Type type = obj.GetType();
PropertyInfo property = type.GetProperty(name);
property.SetValue(obj, oldValue, null);
}
The PropertyGrid.PropertyValuechanged event has this callback:
void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
if (e.ChangedItem.Value is string && e.ChangedItem.Value.ToString() == "")
{
Revert(propertyGrid1.SelectedObject, e.ChangedItem.Label, e.OldValue.ToString());
}
}
The IF-satement will detect any new values which is an empty string.
Here is the problem
As the DisplayName of each property in the PropertyGrid is localized the PropertyValueChangedEventArgs.ChangedItem.Label will contain the localized name and not the actual name of the property.
For instance the Person.FirstName property will be localized to "First name". Therefore the Revert() method will try to get a property called "First name" as name instead of "FirstName". This of course will not work.
I have search for ways to get the actual property which was changed. It seems almost impossible...
But with the debug in Visual Studio I can see that the
PropertyValueChangedEventArgs.ChangedItem
is a base class of the internal .Net Framework class
System.Windows.Forms.PropertyGridInternal.PropertyDescriptorGridEntry Read more about it here[^]
This class contain a property called "PropertyName" which is the exact name as the property's actual name!!!
With reflection I have tried to get this class by trying:
void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
if (e.ChangedItem.Value.ToString() == "")
{
GridItem item = e.ChangedItem;
object[] objs = item.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine(objs.Length);
object o = item.GetType().GetMember("parentPE");
}
}
In the object[] array it seems to be a field which is name "parentPE". This is of type:
System.Windows.Forms.PropertyGridInternal.GridEntry
I have no luck getting the object
Is there a solution for this?
Note:
I'm aware I should not use reflection to access internal classes of the .NET framework. But I cannot see any other solution in the moment. I'm all for any other solutions.
Best regards,
/Steffe
|
|
|
|
|
The ChangedItem property is declared as the public GridItem type[^].
That type exposes a property called PropertyDescriptor [^], which returns a PropertyDescriptor instance[^].
The PropertyDescriptor class has a property called Name [^], which returns the name of the property without any localization.
void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
{
PropertyDescriptor theProperty = e.PropertyDescriptor;
if (theProperty != null)
{
string propertyName = theProperty.Name;
...
}
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thank you very very much!
/Steffe
|
|
|
|
|
Mc_Topaz wrote: * I cannot allow an empty string for any properties. * I want a revert
functionallity to revert to the old value.
This is easily done in each of your properties Set code. Just check the value of the incoming string and don't set the new value in the backing field of the property if it's empty or null.
You don't need any of the PropertyGrid code to do this.
Localized property names don't even come into play.
|
|
|
|
|
Mc_Topaz wrote: But I cannot see any other solution in the moment. To add to the other comments; if it depends on internals, then it is not a solution - it's a dirty hack that may stop working without any warning.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Eddy Vluggen wrote: may stop working
Then again it might not.
|
|
|
|
|
..only if you see "hope and pray" as a viable strategy
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
Nice to see Luc is still remembered!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
|
I am new to this control and was given task on this i don't know how to bind data or document to this document viewer please help me anyone.
|
|
|
|
|
I've never heard of it. Where's the documentation?
There are only 10 types of people in the world, those who understand binary and those who don't.
|
|
|
|
|
If you've got questions about a specific library, your best place to ask is in a forum dedicated to that library.
I doubt any of the regulars here has ever heard of the control you're talking about so it's very unlikely you're ever going to get an answer on it here.
Wow! Look what I found: A Support tab[^] that has Support Forums, Product Documentation, Getting Started Tutorials and Programmer's Guide and Reference!
All you had to do was go to their website and you would have found exactly what you're looking for, plus product focused support, if you just put the tiniest bit of effort into looking for it.
modified 11-Sep-14 19:04pm.
|
|
|
|
|
Oh, he's on my Watch List big time now.
|
|
|
|
|
Yeah, after looking at this guys history, I see what you mean.
Has this putz ever heard of Google?
|
|
|
|
|
I have to start timer at 12AM daily. It has to execute 4 items i have with 15min interval
i.e, item1 should be executed @12, item2 @12 15 and so on
i have written below code:
To start timer @12Am :-
private void SetTimerValue()
{
//// trigger the event at 12 AM.
DateTime requiredTime = DateTime.Today.AddHours(0).AddMinutes(00);
if (DateTime.Now > requiredTime)
{
requiredTime = requiredTime.AddDays(1);
}
TimeSpan periodTS = requiredTime - DateTime.Now;
myTimer = new System.Threading.Timer(new TimerCallback(TimerAction), null, 0, (long)periodTS.TotalMilliseconds);
}
In TimerAction i have 4 items which has to be called @ 15min interval
public void TimerAction(object e)
{
var collection = new List<string> { "item1", "item2", "item3", item4" };
// When timer is 12am, execute item1
// When timer is 12 15am, execute item2
// When timer is 12 30am, execute item3
// When timer is 12 45am, execute item4
}
My question is :
1. Can i create seperate timer inside TimerAction method?
2. How should i loop and execute all these 4 items?
3. Is there any better approach?. Please guide me to do this.
|
|
|
|