|
Richard Deeming wrote: The Select converts the returned value to an IObservable<TResult> , where TResult is the type of the property you're observing. It does this by ignoring the EventArgs , and retrieving the current value of the property instead.
I see, makes sence now.
Richard Deeming wrote: NB: Since it doesn't use a WeakReference , the returned object will keep the target alive, which could potentially cause a memory leak.
Yes, that was the thing I was getting at in the end. The examples around the web seems to jsut wrap the ProeprtyObserver inside a Propertyobserver, only changing the the sender from a straong to a weak referance. They dont really seem to care about the WeakEventManager at all. The reason I liked the first example, was that I could see that I could implement the WeakEventManager directly in it, exchanging the PropertyDescriptor. But seems like that is not nessecary?
|
|
|
|
|
I suspect the Rx libraries have changed since that message was posted in 2011.
In the version I have (2.2.0.0), the FromEvent overload that you're trying to call has the following signature:
IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(
Func<Action<TEventArgs>, TDelegate> conversion,
Action<TDelegate> addHandler,
Action<TDelegate> removeHandler);
The conversion parameter that's causing confusion is a function which takes a single parameter (d ) and returns an EventHandler instance. The parameter is an action which takes a single EventArgs parameter.
Therefore, d.Invoke has the signature:
void Invoke(EventArgs e);
whereas the EventHandler delegate you're trying to return has the signature:
void Invoke(object sender, EventArgs e);
Obviously, those signatures are not compatible. You need to return another lambda method / delegate which matches the EventHandler signature, and passes the second parameter (e ) to the action (d ):
d => (sender, e) => d(e)
These nested lambdas can be quite confusing. Breaking it down, you end up with something similar to this:
private sealed class TheClosure
{
public Action<EventArgs> TheActionToCall;
public void TheEventHandler(object sender, EventArgs e)
{
TheActionToCall(e);
}
}
private static EventHandler Conversion(Action<EventArgs> d)
{
TheClosure closure = new TheClosure();
closure.TheActionToCall = d;
return closure.TheEventHandler;
}
...
Func<Action<EventArgs>, EventHandler> conversion = Conversion;
return Observable.FromEvent<EventHandler, EventArgs>(conversion, ...).Select(ignored => getter(target));
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
|
You're feeding a PropertyChangedEventHandler into the Observable but AddValueChanged(..) and RemoveValueChanged(..) expect a plain EventHandler. So for the first argument of Observable.FromEvent(..) you have to create a delegate that takes the PropertyChangedEventHandler and returns an EventHandler:
return Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler =>
{
EventHandler handler = (s, e) => propertyChangedHandler(e);
return handler;
},
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
.Select(x => propertyExpr.Compile()(target)); Or shorter syntax:
return Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler => (s, e) => propertyChangedHandler(e),
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
.Select(x => propertyExpr.Compile()(target));
Edit: Too slow..
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
 Yes, working my way through the answers
But I cant get your last line of code to compile, I had to do this:
public static class ObservableEx
{
public static IObservable<TResult> FromPropertyChanged<T, TResult>(T target, Expression<Func<T, TResult>> property)
{
Contract.Requires(target != null);
Contract.Requires(property != null);
var body = property.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
var propertyInfo = body.Member as PropertyInfo;
if (propertyInfo == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
string propertyName = propertyInfo.Name;
var propertyDescriptor = (from p in TypeDescriptor.GetProperties(target).Cast<PropertyDescriptor>()
where string.Equals(p.Name, propertyName, StringComparison.Ordinal)
select p)
.Single();
if (!propertyDescriptor.SupportsChangeEvents)
throw new ArgumentException("The specified property does not support change events.", "property");
var getter = property.Compile();
return from e in Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler => (s, e) => propertyChangedHandler(e),
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
select getter(target);
}
}
And the result will only return the actual value thats changed, not the sender and event args.
|
|
|
|
|
Kenneth Haugland wrote: But I cant get your last line of code to compile Sorry, I renamed property to propertyExpr (because it's an Expression) without mentioning it.
Kenneth Haugland wrote: And the result will only return the actual value thats changed, not the sender and event args. That's the case for all the so far shown solutions in this thread. If you want to have the sender and event args you would have to change some stuff:
public class PropertyChangedResult<TTarget, TProperty>
{
public TTarget Target { get; private set; }
public TProperty Value { get; private set; }
public EventArgs EventArgs { get; private set; }
public PropertyChangedResult(TTarget target, TProperty value, EventArgs e)
{
Target = target;
Value = value;
EventArgs = e;
}
}
public static IObservable<PropertyChangedResult<TTarget, TProperty>> FromPropertyChanged<TTarget, TProperty>(TTarget target, Expression<Func<TTarget, TProperty>> propertyExpr)
{
Contract.Requires(target != null);
Contract.Requires(property != null);
var body = propertyExpr.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
var propertyInfo = body.Member as PropertyInfo;
if (propertyInfo == null)
throw new ArgumentException("The specified expression does not reference a property.", "property");
string propertyName = propertyInfo.Name;
var propertyDescriptor = (from p in TypeDescriptor.GetProperties(target).Cast<PropertyDescriptor>()
where string.Equals(p.Name, propertyName, StringComparison.Ordinal)
select p)
.Single();
if (!propertyDescriptor.SupportsChangeEvents)
throw new ArgumentException("The specified property does not support change events.", "property");
return Observable.FromEvent<EventHandler, EventArgs>(
propertyChangedHandler => (s, e) => propertyChangedHandler(e),
h => propertyDescriptor.AddValueChanged(target, h),
h => propertyDescriptor.RemoveValueChanged(target, h))
.Select(e => new PropertyChangedResult<TTarget, TProperty>(target, propertyExpr.Compile()(target), e));
}
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
Sascha Lefèvre wrote: If you want to have the sender and event args you would have to change some stuff:
Thank you. I realize now I have some catching up to do regarding about Lambda Expression Trees[^].
|
|
|
|
|
Is it possible to write code to enable and disable the DNS Client service using c #?
something like:
private void button1_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
If possible .... how to do it, and if not possible... I apologize. Thanks.
I mean this:
http://s23.postimg.org/gapmc008r/Capture.png[^]
|
|
|
|
|
Offhand I know how to do it from the command prompt, soooo:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C sc stop dnscache";
process.StartInfo = startInfo;
process.Start();
Quick code cribbed from SO at c# - Run Command Prompt Commands - Stack Overflow[^]. Credit where it's due.
|
|
|
|
|
Many thanks, it works. I ask for one more question. (example, something like)
When I run my program, if the DNS Client = Enabled (button1.Enabled = false, button2.Enabled = true),
and if the DNS Client = Disabled (button1.Enabled = true, button2.Enabled = false)
Thanks.
|
|
|
|
|
|
|
Thank you. I thought the DNS Client. I set the wrong image. I apologize.
|
|
|
|
|
1448281492 is an Utc-Date (as a decimal?) now i will get these date as a date of my time zone.
Can you may help me?
|
|
|
|
|
|
Sascha Lefèvre wrote: DateTime-
Keep in mind that unfortunately, DateTime, ignores time zone.
One should not confuse that with, for example, assuming that it is the same as UTC, because that would be wrong.
One should strive to use DateTimeOffset instead.
|
|
|
|
|
If those are the number of ticks, then it would be januari the first of your epoch year
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
|
|
|
|
|
You need to know what the number is. Its possible that the number is the number of ticks, and if so, see the answers above. It could also be a Unix timestamp or a Julian Day number, in which case see my tip here[^]
|
|
|
|
|
Where is this data coming from?
It might actually be a C++ time_t date (seconds since midnight 1970).
Best,
John
-- Log Wizard - a Log Viewer that is easy and fun to use!
|
|
|
|
|
THANKS!
I get it!
item.CreationDate is a value from a database: it's the utcDate
so now I have this code:
string einstellDatumTemp = item.creationDate.ToString();
int unixTimestamp = int.Parse(einstellDatumTemp);
DateTime unixYear0 = new DateTime(1970, 1, 1);
long unixTimeStampInTicks = unixTimestamp * TimeSpan.TicksPerSecond;
DateTime dtUnix = new DateTime(unixYear0.Ticks + unixTimeStampInTicks);
|
|
|
|
|
The number looks to me like a standard Windows Time value and equates to the UTC time 12:24:52 Mon Nov 23 2015. You can use any of the standard .NET DateTime methods to display it as local time, according to your timezone.
|
|
|
|
|
Member 11916735 wrote: as a date of my time zone.
Better be very sure that it is your time zone.
Good to go if that number is being generated by your computer. But if is coming from another source (computer, database, etc) then you need to determine that.
|
|
|
|
|
Hello Eerry Body,
I'm working on an application in C # which allows to upgrade a Postgresql database to another database.
here is my code
namespace insert
{
class Program
{
static void Main(string[] args)
{
string connString = "DSN=pg_prd;Database=RPD;User Id=postgres;Password=*****;";
OdbcConnection conn = new OdbcConnection(connString);
OdbcCommand command = conn.CreateCommand();
command.CommandText = "Select etb,nobl,poidsb from t_thisdet";
conn.Open();
OdbcDataAdapter MyAdapter = new OdbcDataAdapter();
MyAdapter.SelectCommand = command;
DataSet dset = new DataSet("t_thisdet");
DataTable ds1 = new DataTable("ds1");
MyAdapter.Fill(ds1);
conn.Close();
string conn1String = "DSN=testing;Database=RPD;User Id=postgres;Password=****;";
OdbcConnection conn1 = new OdbcConnection(conn1String);
OdbcCommand command2 = conn1.CreateCommand();
conn1.Open();
for (int k = 1; k < ds1.Rows.Count; k++)
{
string etb= ds1.Rows[k][@"etb"].ToString();
string nobl = ds1.Rows[k][@"nobl"].ToString();
string poidsb = ds1.Rows[k][@"poidsb"].ToString();
command2.CommandText="insert into hisdet values ('"+etb+"',"+nobl+","+poidsb+")";
command2.ExecuteNonQuery();
}
conn1.Close();
}
When I run my code I have this error :
System.Data.Odbc.OdbcException: ERROR [42601] ERROR: INSERT has more expressions than target columns;
Error while executing the query.
While the structure of the select query is equal to the structure of the inserte request.
you have some idea about this.
thank you for your help.
|
|
|
|
|
what is the db schema/structure for 'hisdet' ?
it looks like what you are trying to do is insert a row into hisdet, that has 2 columns, but you are supplying 3 values - its not a good way to build a command by the way - you should be using a parameterised statement rather than building it from scratch
Im also worried that the values in your insert statement are inconsistently quoted anyway - why the single outer and then double inner quotes around +etb+ ?
|
|
|
|
|
structure of hisdet :
etb character varying(2),
nobl numeric,
poidsb numeric
hisdet contains 3 columns like select request.
|
|
|
|
|